Skip to content

Commit ab4df90

Browse files
[3.13] gh-149156: Fix perf trampoline crash after fork (GH-150347) (#150393)
1 parent 60d8437 commit ab4df90

2 files changed

Lines changed: 15 additions & 5 deletions

File tree

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Fix an intermittent crash after :func:`os.fork` when perf trampoline
2+
profiling is enabled and the child returns through trampoline frames
3+
inherited from the parent process.

Python/perf_trampoline.c

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -211,16 +211,22 @@ enum perf_trampoline_type {
211211
static void free_code_arenas(void);
212212

213213
static void
214-
perf_trampoline_reset_state(void)
214+
perf_trampoline_clear_code_watcher(void)
215215
{
216-
free_code_arenas();
217216
if (code_watcher_id >= 0) {
218217
PyCode_ClearWatcher(code_watcher_id);
219218
code_watcher_id = -1;
220219
}
221220
extra_code_index = -1;
222221
}
223222

223+
static void
224+
perf_trampoline_reset_state(void)
225+
{
226+
free_code_arenas();
227+
perf_trampoline_clear_code_watcher();
228+
}
229+
224230
static int
225231
perf_trampoline_code_watcher(PyCodeEvent event, PyCodeObject *co)
226232
{
@@ -623,9 +629,10 @@ _PyPerfTrampoline_AfterFork_Child(void)
623629
// After fork, Fini may leave the old code watcher registered
624630
// if trampolined code objects from the parent still exist
625631
// (trampoline_refcount > 0). Clear it unconditionally before
626-
// Init registers a new one, to prevent two watchers sharing
627-
// the same globals and double-decrementing trampoline_refcount.
628-
perf_trampoline_reset_state();
632+
// Init registers a new one, but keep the old arenas mapped: the
633+
// child may still need to return through trampoline frames that
634+
// were on the C stack at fork().
635+
perf_trampoline_clear_code_watcher();
629636
_PyPerfTrampoline_Init(1);
630637
}
631638
}

0 commit comments

Comments
 (0)