mirror of https://github.com/python/cpython.git
gh-112367: Only free perf trampoline arenas at shutdown (#112368)
Signed-off-by: Pablo Galindo <pablogsal@gmail.com>
This commit is contained in:
parent
bfb576ee23
commit
a73aa48e6b
|
@ -101,6 +101,7 @@ extern int _PyPerfTrampoline_SetCallbacks(_PyPerf_Callbacks *);
|
||||||
extern void _PyPerfTrampoline_GetCallbacks(_PyPerf_Callbacks *);
|
extern void _PyPerfTrampoline_GetCallbacks(_PyPerf_Callbacks *);
|
||||||
extern int _PyPerfTrampoline_Init(int activate);
|
extern int _PyPerfTrampoline_Init(int activate);
|
||||||
extern int _PyPerfTrampoline_Fini(void);
|
extern int _PyPerfTrampoline_Fini(void);
|
||||||
|
extern void _PyPerfTrampoline_FreeArenas(void);
|
||||||
extern int _PyIsPerfTrampolineActive(void);
|
extern int _PyIsPerfTrampolineActive(void);
|
||||||
extern PyStatus _PyPerfTrampoline_AfterFork_Child(void);
|
extern PyStatus _PyPerfTrampoline_AfterFork_Child(void);
|
||||||
#ifdef PY_HAVE_PERF_TRAMPOLINE
|
#ifdef PY_HAVE_PERF_TRAMPOLINE
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
Avoid undefined behaviour when using the perf trampolines by not freeing the
|
||||||
|
code arenas until shutdown. Patch by Pablo Galindo
|
|
@ -216,10 +216,24 @@ perf_map_write_entry(void *state, const void *code_addr,
|
||||||
PyMem_RawFree(perf_map_entry);
|
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 = {
|
_PyPerf_Callbacks _Py_perfmap_callbacks = {
|
||||||
NULL,
|
&perf_map_init_state,
|
||||||
&perf_map_write_entry,
|
&perf_map_write_entry,
|
||||||
NULL,
|
&perf_map_free_state,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -415,7 +429,6 @@ _PyPerfTrampoline_SetCallbacks(_PyPerf_Callbacks *callbacks)
|
||||||
trampoline_api.write_state = callbacks->write_state;
|
trampoline_api.write_state = callbacks->write_state;
|
||||||
trampoline_api.free_state = callbacks->free_state;
|
trampoline_api.free_state = callbacks->free_state;
|
||||||
trampoline_api.state = NULL;
|
trampoline_api.state = NULL;
|
||||||
perf_status = PERF_STATUS_OK;
|
|
||||||
#endif
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -434,6 +447,7 @@ _PyPerfTrampoline_Init(int activate)
|
||||||
}
|
}
|
||||||
if (!activate) {
|
if (!activate) {
|
||||||
tstate->interp->eval_frame = NULL;
|
tstate->interp->eval_frame = NULL;
|
||||||
|
perf_status = PERF_STATUS_NO_INIT;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
tstate->interp->eval_frame = py_trampoline_evaluator;
|
tstate->interp->eval_frame = py_trampoline_evaluator;
|
||||||
|
@ -444,6 +458,9 @@ _PyPerfTrampoline_Init(int activate)
|
||||||
if (extra_code_index == -1) {
|
if (extra_code_index == -1) {
|
||||||
return -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;
|
perf_status = PERF_STATUS_OK;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -454,16 +471,29 @@ int
|
||||||
_PyPerfTrampoline_Fini(void)
|
_PyPerfTrampoline_Fini(void)
|
||||||
{
|
{
|
||||||
#ifdef PY_HAVE_PERF_TRAMPOLINE
|
#ifdef PY_HAVE_PERF_TRAMPOLINE
|
||||||
|
if (perf_status != PERF_STATUS_OK) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
PyThreadState *tstate = _PyThreadState_GET();
|
PyThreadState *tstate = _PyThreadState_GET();
|
||||||
if (tstate->interp->eval_frame == py_trampoline_evaluator) {
|
if (tstate->interp->eval_frame == py_trampoline_evaluator) {
|
||||||
tstate->interp->eval_frame = NULL;
|
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;
|
extra_code_index = -1;
|
||||||
|
perf_status = PERF_STATUS_NO_INIT;
|
||||||
#endif
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _PyPerfTrampoline_FreeArenas(void) {
|
||||||
|
#ifdef PY_HAVE_PERF_TRAMPOLINE
|
||||||
|
free_code_arenas();
|
||||||
|
#endif
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
PyUnstable_PerfTrampoline_SetPersistAfterFork(int enable){
|
PyUnstable_PerfTrampoline_SetPersistAfterFork(int enable){
|
||||||
#ifdef PY_HAVE_PERF_TRAMPOLINE
|
#ifdef PY_HAVE_PERF_TRAMPOLINE
|
||||||
|
@ -477,8 +507,8 @@ PyStatus
|
||||||
_PyPerfTrampoline_AfterFork_Child(void)
|
_PyPerfTrampoline_AfterFork_Child(void)
|
||||||
{
|
{
|
||||||
#ifdef PY_HAVE_PERF_TRAMPOLINE
|
#ifdef PY_HAVE_PERF_TRAMPOLINE
|
||||||
PyUnstable_PerfMapState_Fini();
|
|
||||||
if (persist_after_fork) {
|
if (persist_after_fork) {
|
||||||
|
_PyPerfTrampoline_Fini();
|
||||||
char filename[256];
|
char filename[256];
|
||||||
pid_t parent_pid = getppid();
|
pid_t parent_pid = getppid();
|
||||||
snprintf(filename, sizeof(filename), "/tmp/perf-%d.map", parent_pid);
|
snprintf(filename, sizeof(filename), "/tmp/perf-%d.map", parent_pid);
|
||||||
|
|
|
@ -1797,6 +1797,7 @@ finalize_interp_clear(PyThreadState *tstate)
|
||||||
_PyArg_Fini();
|
_PyArg_Fini();
|
||||||
_Py_ClearFileSystemEncoding();
|
_Py_ClearFileSystemEncoding();
|
||||||
_PyPerfTrampoline_Fini();
|
_PyPerfTrampoline_Fini();
|
||||||
|
_PyPerfTrampoline_FreeArenas();
|
||||||
}
|
}
|
||||||
|
|
||||||
finalize_interp_types(tstate->interp);
|
finalize_interp_types(tstate->interp);
|
||||||
|
@ -1854,7 +1855,6 @@ Py_FinalizeEx(void)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
_PyAtExit_Call(tstate->interp);
|
_PyAtExit_Call(tstate->interp);
|
||||||
PyUnstable_PerfMapState_Fini();
|
|
||||||
|
|
||||||
/* Copy the core config, PyInterpreterState_Delete() free
|
/* Copy the core config, PyInterpreterState_Delete() free
|
||||||
the core config memory */
|
the core config memory */
|
||||||
|
|
Loading…
Reference in New Issue