]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-112367: Only free perf trampoline arenas at shutdown (#112368)
authorPablo Galindo Salgado <Pablogsal@gmail.com>
Fri, 1 Dec 2023 13:20:51 +0000 (13:20 +0000)
committerGitHub <noreply@github.com>
Fri, 1 Dec 2023 13:20:51 +0000 (13:20 +0000)
Signed-off-by: Pablo Galindo <pablogsal@gmail.com>
Include/internal/pycore_ceval.h
Misc/NEWS.d/next/Core and Builtins/2023-11-24-14-10-57.gh-issue-112367.9z1IDp.rst [new file with mode: 0644]
Python/perf_trampoline.c
Python/pylifecycle.c

index c372b7224fb047b88d899924c2753c2cc7cf837c..3f7ac922bdf45156abf356384d9f1ba3de92477f 100644 (file)
@@ -101,6 +101,7 @@ extern int _PyPerfTrampoline_SetCallbacks(_PyPerf_Callbacks *);
 extern void _PyPerfTrampoline_GetCallbacks(_PyPerf_Callbacks *);
 extern int _PyPerfTrampoline_Init(int activate);
 extern int _PyPerfTrampoline_Fini(void);
+extern void _PyPerfTrampoline_FreeArenas(void);
 extern int _PyIsPerfTrampolineActive(void);
 extern PyStatus _PyPerfTrampoline_AfterFork_Child(void);
 #ifdef PY_HAVE_PERF_TRAMPOLINE
diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-11-24-14-10-57.gh-issue-112367.9z1IDp.rst b/Misc/NEWS.d/next/Core and Builtins/2023-11-24-14-10-57.gh-issue-112367.9z1IDp.rst
new file mode 100644 (file)
index 0000000..991e45a
--- /dev/null
@@ -0,0 +1,2 @@
+Avoid undefined behaviour when using the perf trampolines by not freeing the
+code arenas until shutdown. Patch by Pablo Galindo
index 208ced6c101dce943ed68a17cb35984ccbc2e532..540b650192ed34fd4ea58890352e862d72818d82 100644 (file)
@@ -216,10 +216,24 @@ perf_map_write_entry(void *state, const void *code_addr,
     PyMem_RawFree(perf_map_entry);
 }
 
+static void*
+perf_map_init_state(void)
+{
+    PyUnstable_PerfMapState_Init();
+    return NULL;
+}
+
+static int
+perf_map_free_state(void *state)
+{
+    PyUnstable_PerfMapState_Fini();
+    return 0;
+}
+
 _PyPerf_Callbacks _Py_perfmap_callbacks = {
-    NULL,
+    &perf_map_init_state,
     &perf_map_write_entry,
-    NULL,
+    &perf_map_free_state,
 };
 
 static int
@@ -415,7 +429,6 @@ _PyPerfTrampoline_SetCallbacks(_PyPerf_Callbacks *callbacks)
     trampoline_api.write_state = callbacks->write_state;
     trampoline_api.free_state = callbacks->free_state;
     trampoline_api.state = NULL;
-    perf_status = PERF_STATUS_OK;
 #endif
     return 0;
 }
@@ -434,6 +447,7 @@ _PyPerfTrampoline_Init(int activate)
     }
     if (!activate) {
         tstate->interp->eval_frame = NULL;
+        perf_status = PERF_STATUS_NO_INIT;
     }
     else {
         tstate->interp->eval_frame = py_trampoline_evaluator;
@@ -444,6 +458,9 @@ _PyPerfTrampoline_Init(int activate)
         if (extra_code_index == -1) {
             return -1;
         }
+        if (trampoline_api.state == NULL && trampoline_api.init_state != NULL) {
+            trampoline_api.state = trampoline_api.init_state();
+        }
         perf_status = PERF_STATUS_OK;
     }
 #endif
@@ -454,16 +471,29 @@ int
 _PyPerfTrampoline_Fini(void)
 {
 #ifdef PY_HAVE_PERF_TRAMPOLINE
+    if (perf_status != PERF_STATUS_OK) {
+        return 0;
+    }
     PyThreadState *tstate = _PyThreadState_GET();
     if (tstate->interp->eval_frame == py_trampoline_evaluator) {
         tstate->interp->eval_frame = NULL;
     }
-    free_code_arenas();
+    if (perf_status == PERF_STATUS_OK) {
+        trampoline_api.free_state(trampoline_api.state);
+    }
     extra_code_index = -1;
+    perf_status = PERF_STATUS_NO_INIT;
 #endif
     return 0;
 }
 
+void _PyPerfTrampoline_FreeArenas(void) {
+#ifdef PY_HAVE_PERF_TRAMPOLINE
+    free_code_arenas();
+#endif
+    return;
+}
+
 int
 PyUnstable_PerfTrampoline_SetPersistAfterFork(int enable){
 #ifdef PY_HAVE_PERF_TRAMPOLINE
@@ -477,8 +507,8 @@ PyStatus
 _PyPerfTrampoline_AfterFork_Child(void)
 {
 #ifdef PY_HAVE_PERF_TRAMPOLINE
-    PyUnstable_PerfMapState_Fini();
     if (persist_after_fork) {
+        _PyPerfTrampoline_Fini();
         char filename[256];
         pid_t parent_pid = getppid();
         snprintf(filename, sizeof(filename), "/tmp/perf-%d.map", parent_pid);
index ac8d5208322882aa268ded84f93d13045e225b1e..aff67d7a835e89889cdd3f9560f65643ed30b0a8 100644 (file)
@@ -1797,6 +1797,7 @@ finalize_interp_clear(PyThreadState *tstate)
         _PyArg_Fini();
         _Py_ClearFileSystemEncoding();
         _PyPerfTrampoline_Fini();
+        _PyPerfTrampoline_FreeArenas();
     }
 
     finalize_interp_types(tstate->interp);
@@ -1854,7 +1855,6 @@ Py_FinalizeEx(void)
      */
 
     _PyAtExit_Call(tstate->interp);
-    PyUnstable_PerfMapState_Fini();
 
     /* Copy the core config, PyInterpreterState_Delete() free
        the core config memory */