Skip to content

Commit 4dc7463

Browse files
bpo-46430: Fix memory leak in interned strings of deep-frozen modules (GH-31549)
1 parent 042f31d commit 4dc7463

File tree

6 files changed

+21
-6
lines changed

6 files changed

+21
-6
lines changed

Include/internal/pycore_pylifecycle.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ extern PyStatus _Py_HashRandomization_Init(const PyConfig *);
6565
extern PyStatus _PyImportZip_Init(PyThreadState *tstate);
6666
extern PyStatus _PyGC_Init(PyInterpreterState *interp);
6767
extern PyStatus _PyAtExit_Init(PyInterpreterState *interp);
68-
68+
extern void _Py_Deepfreeze_Init(void);
6969

7070
/* Various internal finalizers */
7171

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix memory leak in interned strings of deep-frozen modules.

Programs/_bootstrap_python.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,13 @@
1414
#include "Python/frozen_modules/importlib._bootstrap_external.h"
1515
/* End includes */
1616

17-
/* Empty finalizer for deepfrozen modules*/
17+
/* Empty initializer for deepfrozen modules */
18+
void _Py_Deepfreeze_Init(void)
19+
{
20+
}
21+
/* Empty finalizer for deepfrozen modules */
1822
void
19-
_Py_Deepfreeze_Fini(void)
23+
_Py_Deepfreeze_Fini(void)
2024
{
2125
}
2226

Programs/_freeze_module.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@
2222
#include <unistd.h>
2323
#endif
2424

25+
/* Empty initializer for deepfrozen modules */
26+
void _Py_Deepfreeze_Init(void)
27+
{
28+
}
2529
/* Empty finalizer for deepfrozen modules */
2630
void
2731
_Py_Deepfreeze_Fini(void)

Python/pylifecycle.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -754,7 +754,6 @@ pycore_init_types(PyInterpreterState *interp)
754754
if (_PyStatus_EXCEPTION(status)) {
755755
return status;
756756
}
757-
758757
return _PyStatus_OK();
759758
}
760759

@@ -827,7 +826,10 @@ pycore_interp_init(PyThreadState *tstate)
827826
if (_PyStatus_EXCEPTION(status)) {
828827
return status;
829828
}
830-
829+
// Intern strings in deep-frozen modules first so that others
830+
// can use it instead of creating a heap allocated string.
831+
_Py_Deepfreeze_Init();
832+
831833
status = pycore_init_types(interp);
832834
if (_PyStatus_EXCEPTION(status)) {
833835
goto done;

Tools/scripts/deepfreeze.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ def __init__(self, file: TextIO) -> None:
110110
self.hits, self.misses = 0, 0
111111
self.patchups: list[str] = []
112112
self.deallocs: list[str] = []
113+
self.interns: list[str] = []
113114
self.write('#include "Python.h"')
114115
self.write('#include "internal/pycore_gc.h"')
115116
self.write('#include "internal/pycore_code.h"')
@@ -279,7 +280,7 @@ def generate_code(self, name: str, code: types.CodeType) -> str:
279280
self.write(f".co_cellvars = {co_cellvars},")
280281
self.write(f".co_freevars = {co_freevars},")
281282
self.deallocs.append(f"_PyStaticCode_Dealloc(&{name});")
282-
self.patchups.append(f"_PyStaticCode_InternStrings(&{name});")
283+
self.interns.append(f"_PyStaticCode_InternStrings(&{name});")
283284
return f"& {name}.ob_base"
284285

285286
def generate_tuple(self, name: str, t: Tuple[object, ...]) -> str:
@@ -446,6 +447,9 @@ def generate(args: list[str], output: TextIO) -> None:
446447
with printer.block(f"void\n_Py_Deepfreeze_Fini(void)"):
447448
for p in printer.deallocs:
448449
printer.write(p)
450+
with printer.block(f"void\n_Py_Deepfreeze_Init(void)"):
451+
for p in printer.interns:
452+
printer.write(p)
449453
if verbose:
450454
print(f"Cache hits: {printer.hits}, misses: {printer.misses}")
451455

0 commit comments

Comments
 (0)