https://github.com/python/cpython/commit/09a34f1f659cd66c380353cf9b8b0247789128cc
commit: 09a34f1f659cd66c380353cf9b8b0247789128cc
branch: 3.14
author: Miss Islington (bot) <31488909+miss-isling...@users.noreply.github.com>
committer: colesbury <colesb...@gmail.com>
date: 2025-05-23T19:49:13Z
summary:

[3.14] gh-134381: Fix RuntimeError when starting not-yet started Thread after 
fork (gh-134514) (gh-134596)

(cherry picked from commit 9a2346df861f26d5f8d054ad2f9c37134dee3822)

Co-authored-by: Jiucheng(Oliver) <git.jiuch...@gmail.com>

files:
A 
Misc/NEWS.d/next/Core_and_Builtins/2025-05-22-14-48-19.gh-issue-134381.2BXhth.rst
M Lib/test/_test_multiprocessing.py
M Modules/_threadmodule.c

diff --git a/Lib/test/_test_multiprocessing.py 
b/Lib/test/_test_multiprocessing.py
index 8cc4e46fa12a68..63f522f6ecce21 100644
--- a/Lib/test/_test_multiprocessing.py
+++ b/Lib/test/_test_multiprocessing.py
@@ -6832,6 +6832,28 @@ def f(x): return x*x
         self.assertEqual("332833500", out.decode('utf-8').strip())
         self.assertFalse(err, msg=err.decode('utf-8'))
 
+    def test_forked_thread_not_started(self):
+        # gh-134381: Ensure that a thread that has not been started yet in
+        # the parent process can be started within a forked child process.
+
+        if multiprocessing.get_start_method() != "fork":
+            self.skipTest("fork specific test")
+
+        q = multiprocessing.Queue()
+        t = threading.Thread(target=lambda: q.put("done"), daemon=True)
+
+        def child():
+            t.start()
+            t.join()
+
+        p = multiprocessing.Process(target=child)
+        p.start()
+        p.join(support.SHORT_TIMEOUT)
+
+        self.assertEqual(p.exitcode, 0)
+        self.assertEqual(q.get_nowait(), "done")
+        close_queue(q)
+
 
 #
 # Mixins
diff --git 
a/Misc/NEWS.d/next/Core_and_Builtins/2025-05-22-14-48-19.gh-issue-134381.2BXhth.rst
 
b/Misc/NEWS.d/next/Core_and_Builtins/2025-05-22-14-48-19.gh-issue-134381.2BXhth.rst
new file mode 100644
index 00000000000000..aa8900296ae2fc
--- /dev/null
+++ 
b/Misc/NEWS.d/next/Core_and_Builtins/2025-05-22-14-48-19.gh-issue-134381.2BXhth.rst
@@ -0,0 +1 @@
+Fix :exc:`RuntimeError` when using a not-started :class:`threading.Thread` 
after calling :func:`os.fork`
diff --git a/Modules/_threadmodule.c b/Modules/_threadmodule.c
index f676659af369f6..73739d24f33c05 100644
--- a/Modules/_threadmodule.c
+++ b/Modules/_threadmodule.c
@@ -281,6 +281,12 @@ _PyThread_AfterFork(struct _pythread_runtime_state *state)
             continue;
         }
 
+        // Keep handles for threads that have not been started yet. They are
+        // safe to start in the child process.
+        if (handle->state == THREAD_HANDLE_NOT_STARTED) {
+            continue;
+        }
+
         // Mark all threads as done. Any attempts to join or detach the
         // underlying OS thread (if any) could crash. We are the only thread;
         // it's safe to set this non-atomically.

_______________________________________________
Python-checkins mailing list -- python-checkins@python.org
To unsubscribe send an email to python-checkins-le...@python.org
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: arch...@mail-archive.com

Reply via email to