File tree 3 files changed +29
-0
lines changed
Misc/NEWS.d/next/Core_and_Builtins 3 files changed +29
-0
lines changed Original file line number Diff line number Diff line change @@ -6844,6 +6844,28 @@ def f(x): return x*x
6844
6844
self .assertEqual ("332833500" , out .decode ('utf-8' ).strip ())
6845
6845
self .assertFalse (err , msg = err .decode ('utf-8' ))
6846
6846
6847
+ def test_forked_thread_not_started (self ):
6848
+ # gh-134381: Ensure that a thread that has not been started yet in
6849
+ # the parent process can be started within a forked child process.
6850
+
6851
+ if multiprocessing .get_start_method () != "fork" :
6852
+ self .skipTest ("fork specific test" )
6853
+
6854
+ q = multiprocessing .Queue ()
6855
+ t = threading .Thread (target = lambda : q .put ("done" ), daemon = True )
6856
+
6857
+ def child ():
6858
+ t .start ()
6859
+ t .join ()
6860
+
6861
+ p = multiprocessing .Process (target = child )
6862
+ p .start ()
6863
+ p .join (support .SHORT_TIMEOUT )
6864
+
6865
+ self .assertEqual (p .exitcode , 0 )
6866
+ self .assertEqual (q .get_nowait (), "done" )
6867
+ close_queue (q )
6868
+
6847
6869
6848
6870
#
6849
6871
# 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 @@ -296,6 +296,12 @@ _PyThread_AfterFork(struct _pythread_runtime_state *state)
296
296
continue ;
297
297
}
298
298
299
+ // Keep handles for threads that have not been started yet. They are
300
+ // safe to start in the child process.
301
+ if (handle -> state == THREAD_HANDLE_NOT_STARTED ) {
302
+ continue ;
303
+ }
304
+
299
305
// Mark all threads as done. Any attempts to join or detach the
300
306
// underlying OS thread (if any) could crash. We are the only thread;
301
307
// it's safe to set this non-atomically.
You can’t perform that action at this time.
0 commit comments