Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 11232c1

Browse files
authored
[3.12] gh-112367: Only free perf trampoline arenas at shutdown (GH-112368) (#112590)
(cherry picked from commit a73aa48) Signed-off-by: Pablo Galindo <[email protected]>
1 parent 4f919cf commit 11232c1

File tree

4 files changed

+38
-5
lines changed

4 files changed

+38
-5
lines changed

Include/internal/pycore_ceval.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ extern int _PyPerfTrampoline_SetCallbacks(_PyPerf_Callbacks *);
7474
extern void _PyPerfTrampoline_GetCallbacks(_PyPerf_Callbacks *);
7575
extern int _PyPerfTrampoline_Init(int activate);
7676
extern int _PyPerfTrampoline_Fini(void);
77+
extern void _PyPerfTrampoline_FreeArenas(void);
7778
extern int _PyIsPerfTrampolineActive(void);
7879
extern PyStatus _PyPerfTrampoline_AfterFork_Child(void);
7980
#ifdef PY_HAVE_PERF_TRAMPOLINE
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Avoid undefined behaviour when using the perf trampolines by not freeing the
2+
code arenas until shutdown. Patch by Pablo Galindo

Python/perf_trampoline.c

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -216,10 +216,24 @@ perf_map_write_entry(void *state, const void *code_addr,
216216
PyMem_RawFree(perf_map_entry);
217217
}
218218

219+
static void*
220+
perf_map_init_state(void)
221+
{
222+
PyUnstable_PerfMapState_Init();
223+
return NULL;
224+
}
225+
226+
static int
227+
perf_map_free_state(void *state)
228+
{
229+
PyUnstable_PerfMapState_Fini();
230+
return 0;
231+
}
232+
219233
_PyPerf_Callbacks _Py_perfmap_callbacks = {
220-
NULL,
234+
&perf_map_init_state,
221235
&perf_map_write_entry,
222-
NULL,
236+
&perf_map_free_state,
223237
};
224238

225239
static int
@@ -398,11 +412,17 @@ _PyPerfTrampoline_SetCallbacks(_PyPerf_Callbacks *callbacks)
398412
trampoline_api.write_state = callbacks->write_state;
399413
trampoline_api.free_state = callbacks->free_state;
400414
trampoline_api.state = NULL;
401-
perf_status = PERF_STATUS_OK;
402415
#endif
403416
return 0;
404417
}
405418

419+
void _PyPerfTrampoline_FreeArenas(void) {
420+
#ifdef PY_HAVE_PERF_TRAMPOLINE
421+
free_code_arenas();
422+
#endif
423+
return;
424+
}
425+
406426
int
407427
_PyPerfTrampoline_Init(int activate)
408428
{
@@ -417,6 +437,7 @@ _PyPerfTrampoline_Init(int activate)
417437
}
418438
if (!activate) {
419439
tstate->interp->eval_frame = NULL;
440+
perf_status = PERF_STATUS_NO_INIT;
420441
}
421442
else {
422443
tstate->interp->eval_frame = py_trampoline_evaluator;
@@ -427,6 +448,9 @@ _PyPerfTrampoline_Init(int activate)
427448
if (extra_code_index == -1) {
428449
return -1;
429450
}
451+
if (trampoline_api.state == NULL && trampoline_api.init_state != NULL) {
452+
trampoline_api.state = trampoline_api.init_state();
453+
}
430454
perf_status = PERF_STATUS_OK;
431455
}
432456
#endif
@@ -437,12 +461,18 @@ int
437461
_PyPerfTrampoline_Fini(void)
438462
{
439463
#ifdef PY_HAVE_PERF_TRAMPOLINE
464+
if (perf_status != PERF_STATUS_OK) {
465+
return 0;
466+
}
440467
PyThreadState *tstate = _PyThreadState_GET();
441468
if (tstate->interp->eval_frame == py_trampoline_evaluator) {
442469
tstate->interp->eval_frame = NULL;
443470
}
444-
free_code_arenas();
471+
if (perf_status == PERF_STATUS_OK) {
472+
trampoline_api.free_state(trampoline_api.state);
473+
}
445474
extra_code_index = -1;
475+
perf_status = PERF_STATUS_NO_INIT;
446476
#endif
447477
return 0;
448478
}

Python/pylifecycle.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1755,6 +1755,7 @@ finalize_interp_clear(PyThreadState *tstate)
17551755
_Py_ClearFileSystemEncoding();
17561756
_Py_Deepfreeze_Fini();
17571757
_PyPerfTrampoline_Fini();
1758+
_PyPerfTrampoline_FreeArenas();
17581759
}
17591760

17601761
finalize_interp_types(tstate->interp);
@@ -1812,7 +1813,6 @@ Py_FinalizeEx(void)
18121813
*/
18131814

18141815
_PyAtExit_Call(tstate->interp);
1815-
PyUnstable_PerfMapState_Fini();
18161816

18171817
/* Copy the core config, PyInterpreterState_Delete() free
18181818
the core config memory */

0 commit comments

Comments
 (0)