@@ -211,16 +211,22 @@ enum perf_trampoline_type {
211211static void free_code_arenas (void );
212212
213213static 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+
224230static int
225231perf_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