]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
bpo-46476: Fix memory leak in code objects generated by deepfreeze (GH-30853)
authorKumar Aditya <59607654+kumaraditya303@users.noreply.github.com>
Thu, 27 Jan 2022 13:03:47 +0000 (18:33 +0530)
committerGitHub <noreply@github.com>
Thu, 27 Jan 2022 13:03:47 +0000 (14:03 +0100)
Add _Py_Deepfreeze_Fini() and _PyStaticCode_Dealloc() functions.

Include/internal/pycore_code.h
Include/internal/pycore_pylifecycle.h
Misc/NEWS.d/next/Core and Builtins/2022-01-24-15-39-34.bpo-46476.cvP1Mr.rst [new file with mode: 0644]
Objects/codeobject.c
Programs/_bootstrap_python.c
Programs/_freeze_module.c
Python/pylifecycle.c
Tools/scripts/deepfreeze.py

index dfc75300315e29a0d8aef55dc33110b7839302ea..884a91f3fb7edff9f6e51e310006191072407e6e 100644 (file)
@@ -276,6 +276,8 @@ void _Py_Specialize_BinaryOp(PyObject *lhs, PyObject *rhs, _Py_CODEUNIT *instr,
                              SpecializedCacheEntry *cache);
 void _Py_Specialize_CompareOp(PyObject *lhs, PyObject *rhs, _Py_CODEUNIT *instr, SpecializedCacheEntry *cache);
 
+/* Deallocator function for static codeobjects used in deepfreeze.py */
+void _PyStaticCode_Dealloc(PyCodeObject *co, _Py_CODEUNIT *firstinstr);
 
 #ifdef Py_STATS
 
index 35e560b42ee0ae7b2ff0a565659c1dbc8ef3dd2b..439bc5b470bb266baa08b52adf4e9da8eff4e777 100644 (file)
@@ -83,6 +83,7 @@ extern void _PyWarnings_Fini(PyInterpreterState *interp);
 extern void _PyAST_Fini(PyInterpreterState *interp);
 extern void _PyAtExit_Fini(PyInterpreterState *interp);
 extern void _PyThread_FiniType(PyInterpreterState *interp);
+extern void _Py_Deepfreeze_Fini(void);
 
 extern PyStatus _PyGILState_Init(_PyRuntimeState *runtime);
 extern PyStatus _PyGILState_SetTstate(PyThreadState *tstate);
diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-01-24-15-39-34.bpo-46476.cvP1Mr.rst b/Misc/NEWS.d/next/Core and Builtins/2022-01-24-15-39-34.bpo-46476.cvP1Mr.rst
new file mode 100644 (file)
index 0000000..2607983
--- /dev/null
@@ -0,0 +1 @@
+Fix memory leak in code objects generated by deepfreeze. Patch by Kumar Aditya.
\ No newline at end of file
index a413b183be8edcaeb31f84552c8c32634b94f78b..f983d66db05d6eadd4b82259149b75c156e5ebec 100644 (file)
@@ -1906,3 +1906,18 @@ _PyCode_ConstantKey(PyObject *op)
     }
     return key;
 }
+
+void 
+_PyStaticCode_Dealloc(PyCodeObject *co, _Py_CODEUNIT *firstinstr)
+{
+    PyMem_Free(co->co_quickened);
+    co->co_quickened = NULL;
+    PyMem_Free(co->co_extra);
+    co->co_extra = NULL;
+    co->co_firstinstr = firstinstr;
+    if (co->co_weakreflist != NULL) {
+        PyObject_ClearWeakRefs((PyObject *)co);
+        co->co_weakreflist = NULL;
+    }
+    co->co_warmup = QUICKENING_INITIAL_WARMUP_VALUE;
+}
index f2103fd5aaae51b457d1f1b848ca02695ee4abe3..f4d0167b62e7123c30f900fd9d702469f63be312 100644 (file)
 #include "Python/frozen_modules/importlib._bootstrap_external.h"
 /* End includes */
 
+/* Empty finalizer for deepfrozen modules*/
+void
+_Py_Deepfreeze_Fini(void) 
+{
+}
+
 /* Note that a negative size indicates a package. */
 
 static const struct _frozen bootstrap_modules[] = {
@@ -103,3 +109,4 @@ error:
     }
     Py_ExitStatusException(status);
 }
+
index b2f1a24016fac87fadcb523ff8131a350f548cde..99a1d4dfc261f3914537dbefdcb0c46f7e06e499 100644 (file)
 #include <unistd.h>
 #endif
 
+/* Empty finalizer for deepfrozen modules */
+void
+_Py_Deepfreeze_Fini(void)
+{
+}
+
 /* To avoid a circular dependency on frozen.o, we create our own structure
    of frozen modules instead, left deliberately blank so as to avoid
    unintentional import of a stale version of _frozen_importlib. */
@@ -235,3 +241,4 @@ error:
     Py_Finalize();
     return 1;
 }
+
index 9d10f94efa732efeef22703dbcf270da8bd32dd1..106e11ea12ff533cf3388fd3ad98cfe335f91c2b 100644 (file)
@@ -1723,6 +1723,7 @@ finalize_interp_clear(PyThreadState *tstate)
         _Py_HashRandomization_Fini();
         _PyArg_Fini();
         _Py_ClearFileSystemEncoding();
+        _Py_Deepfreeze_Fini();
     }
 
     finalize_interp_types(tstate->interp);
index a1ef85ea891a27d2e66364787f3a29f828cc4784..78849390f12604d24ea6720549cfca81425ed17c 100644 (file)
@@ -109,6 +109,7 @@ class Printer:
         self.cache: Dict[tuple[type, object, str], str] = {}
         self.hits, self.misses = 0, 0
         self.patchups: list[str] = []
+        self.deallocs: list[str] = []
         self.write('#include "Python.h"')
         self.write('#include "internal/pycore_gc.h"')
         self.write('#include "internal/pycore_code.h"')
@@ -277,6 +278,7 @@ class Printer:
             self.write(f".co_varnames = {co_varnames},")
             self.write(f".co_cellvars = {co_cellvars},")
             self.write(f".co_freevars = {co_freevars},")
+        self.deallocs.append(f"_PyStaticCode_Dealloc(&{name}, (_Py_CODEUNIT *) {removesuffix(co_code, '.ob_base.ob_base')}.ob_sval);")
         return f"& {name}.ob_base"
 
     def generate_tuple(self, name: str, t: Tuple[object, ...]) -> str:
@@ -440,6 +442,9 @@ def generate(args: list[str], output: TextIO) -> None:
             else:
                 code = compile(fd.read(), f"<frozen {modname}>", "exec")
             printer.generate_file(modname, code)
+    with printer.block(f"void\n_Py_Deepfreeze_Fini(void)"):
+            for p in printer.deallocs:
+                printer.write(p)
     if verbose:
         print(f"Cache hits: {printer.hits}, misses: {printer.misses}")