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

Skip to content

Commit 92b61e4

Browse files
committed
gh-112367: Only free perf trampoline arenas at shutdown
Signed-off-by: Pablo Galindo <[email protected]>
1 parent e9d1360 commit 92b61e4

File tree

5 files changed

+40
-6
lines changed

5 files changed

+40
-6
lines changed

Include/internal/pycore_ceval.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ extern int _PyPerfTrampoline_SetCallbacks(_PyPerf_Callbacks *);
101101
extern void _PyPerfTrampoline_GetCallbacks(_PyPerf_Callbacks *);
102102
extern int _PyPerfTrampoline_Init(int activate);
103103
extern int _PyPerfTrampoline_Fini(void);
104+
extern void _PyPerfTrampoline_FreeArenas(void);
104105
extern int _PyIsPerfTrampolineActive(void);
105106
extern PyStatus _PyPerfTrampoline_AfterFork_Child(void);
106107
#ifdef PY_HAVE_PERF_TRAMPOLINE

Lib/ast.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1277,6 +1277,8 @@ def _write_fstring_inner(self, node, scape_newlines=False):
12771277
self._write_fstring_inner(value, scape_newlines=scape_newlines)
12781278
elif isinstance(node, Constant) and isinstance(node.value, str):
12791279
value = node.value.replace("{", "{{").replace("}", "}}")
1280+
# Escape quotes in the format spec
1281+
value = value.replace("'", "\\'").replace('"', '\\"')
12801282
if scape_newlines:
12811283
value = value.replace("\n", "\\n")
12821284
self.write(value)
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 & 5 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
@@ -444,6 +458,9 @@ _PyPerfTrampoline_Init(int activate)
444458
if (extra_code_index == -1) {
445459
return -1;
446460
}
461+
if (trampoline_api.state == NULL && trampoline_api.init_state != NULL) {
462+
trampoline_api.state = trampoline_api.init_state();
463+
}
447464
perf_status = PERF_STATUS_OK;
448465
}
449466
#endif
@@ -454,16 +471,29 @@ int
454471
_PyPerfTrampoline_Fini(void)
455472
{
456473
#ifdef PY_HAVE_PERF_TRAMPOLINE
474+
if (perf_status != PERF_STATUS_OK) {
475+
return 0;
476+
}
457477
PyThreadState *tstate = _PyThreadState_GET();
458478
if (tstate->interp->eval_frame == py_trampoline_evaluator) {
459479
tstate->interp->eval_frame = NULL;
460480
}
461-
free_code_arenas();
481+
if (perf_status == PERF_STATUS_OK) {
482+
trampoline_api.free_state(trampoline_api.state);
483+
}
462484
extra_code_index = -1;
463485
#endif
486+
perf_status = PERF_STATUS_NO_INIT;
464487
return 0;
465488
}
466489

490+
void _PyPerfTrampoline_FreeArenas(void) {
491+
#ifdef PY_HAVE_PERF_TRAMPOLINE
492+
free_code_arenas();
493+
#endif
494+
return;
495+
}
496+
467497
int
468498
PyUnstable_PerfTrampoline_SetPersistAfterFork(int enable){
469499
#ifdef PY_HAVE_PERF_TRAMPOLINE
@@ -477,7 +507,7 @@ PyStatus
477507
_PyPerfTrampoline_AfterFork_Child(void)
478508
{
479509
#ifdef PY_HAVE_PERF_TRAMPOLINE
480-
PyUnstable_PerfMapState_Fini();
510+
_PyPerfTrampoline_Fini();
481511
if (persist_after_fork) {
482512
char filename[256];
483513
pid_t parent_pid = getppid();
@@ -488,7 +518,6 @@ _PyPerfTrampoline_AfterFork_Child(void)
488518
} else {
489519
// Restart trampoline in file in child.
490520
int was_active = _PyIsPerfTrampolineActive();
491-
_PyPerfTrampoline_Fini();
492521
if (was_active) {
493522
_PyPerfTrampoline_Init(1);
494523
}

Python/pylifecycle.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1797,6 +1797,7 @@ finalize_interp_clear(PyThreadState *tstate)
17971797
_PyArg_Fini();
17981798
_Py_ClearFileSystemEncoding();
17991799
_PyPerfTrampoline_Fini();
1800+
_PyPerfTrampoline_FreeArenas();
18001801
}
18011802

18021803
finalize_interp_types(tstate->interp);
@@ -1854,7 +1855,6 @@ Py_FinalizeEx(void)
18541855
*/
18551856

18561857
_PyAtExit_Call(tstate->interp);
1857-
PyUnstable_PerfMapState_Fini();
18581858

18591859
/* Copy the core config, PyInterpreterState_Delete() free
18601860
the core config memory */

0 commit comments

Comments
 (0)