File tree Expand file tree Collapse file tree 3 files changed +29
-0
lines changed
Misc/NEWS.d/next/Core_and_Builtins Expand file tree Collapse file tree 3 files changed +29
-0
lines changed Original file line number Diff line number Diff line change @@ -6832,6 +6832,28 @@ def f(x): return x*x
68326832 self .assertEqual ("332833500" , out .decode ('utf-8' ).strip ())
68336833 self .assertFalse (err , msg = err .decode ('utf-8' ))
68346834
6835+ def test_forked_thread_not_started (self ):
6836+ # gh-134381: Ensure that a thread that has not been started yet in
6837+ # the parent process can be started within a forked child process.
6838+
6839+ if multiprocessing .get_start_method () != "fork" :
6840+ self .skipTest ("fork specific test" )
6841+
6842+ q = multiprocessing .Queue ()
6843+ t = threading .Thread (target = lambda : q .put ("done" ), daemon = True )
6844+
6845+ def child ():
6846+ t .start ()
6847+ t .join ()
6848+
6849+ p = multiprocessing .Process (target = child )
6850+ p .start ()
6851+ p .join (support .SHORT_TIMEOUT )
6852+
6853+ self .assertEqual (p .exitcode , 0 )
6854+ self .assertEqual (q .get_nowait (), "done" )
6855+ close_queue (q )
6856+
68356857
68366858#
68376859# Mixins
Original file line number Diff line number Diff line change 1+ Fix :exc: `RuntimeError ` when using a not-started :class: `threading.Thread ` after calling :func: `os.fork `
Original file line number Diff line number Diff line change @@ -281,6 +281,12 @@ _PyThread_AfterFork(struct _pythread_runtime_state *state)
281281 continue ;
282282 }
283283
284+ // Keep handles for threads that have not been started yet. They are
285+ // safe to start in the child process.
286+ if (handle -> state == THREAD_HANDLE_NOT_STARTED ) {
287+ continue ;
288+ }
289+
284290 // Mark all threads as done. Any attempts to join or detach the
285291 // underlying OS thread (if any) could crash. We are the only thread;
286292 // it's safe to set this non-atomically.
You can’t perform that action at this time.
0 commit comments