]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
Issue #13817: After fork(), reinit the ad-hoc TLS implementation earlier to fix
authorCharles-François Natali <neologix@free.fr>
Thu, 2 Feb 2012 18:57:19 +0000 (19:57 +0100)
committerCharles-François Natali <neologix@free.fr>
Thu, 2 Feb 2012 18:57:19 +0000 (19:57 +0100)
a random deadlock when fork() is called in a multithreaded process in debug
mode, and make PyOS_AfterFork() more robust.

Lib/test/test_threading.py
Modules/signalmodule.c

index bdb7f1453a15d2acffab56f530ad6160d7fd5e87..e617fa1275a56d85be00f135117fd742bcd0245c 100644 (file)
@@ -635,6 +635,29 @@ class ThreadJoinOnShutdown(BaseTestCase):
         output = "end of worker thread\nend of main thread\n"
         self.assertScriptHasOutput(script, output)
 
+    @unittest.skipUnless(hasattr(os, 'fork'), "needs os.fork()")
+    def test_reinit_tls_after_fork(self):
+        # Issue #13817: fork() would deadlock in a multithreaded program with
+        # the ad-hoc TLS implementation.
+
+        def do_fork_and_wait():
+            # just fork a child process and wait it
+            pid = os.fork()
+            if pid > 0:
+                os.waitpid(pid, 0)
+            else:
+                os._exit(0)
+
+        # start a bunch of threads that will fork() child processes
+        threads = []
+        for i in range(16):
+            t = threading.Thread(target=do_fork_and_wait)
+            threads.append(t)
+            t.start()
+
+        for t in threads:
+            t.join()
+
 
 class ThreadingExceptionTests(BaseTestCase):
     # A RuntimeError should be raised if Thread.start() is called
index f306bba16f53965aede614bdbc3c57c93f09c1ca..908c2ee994044c0f968b52ba78154b6dedefe32b 100644 (file)
@@ -976,10 +976,12 @@ void
 PyOS_AfterFork(void)
 {
 #ifdef WITH_THREAD
+    /* PyThread_ReInitTLS() must be called early, to make sure that the TLS API
+     * can be called safely. */
+    PyThread_ReInitTLS();
     PyEval_ReInitThreads();
     main_thread = PyThread_get_thread_ident();
     main_pid = getpid();
     _PyImport_ReInitLock();
-    PyThread_ReInitTLS();
 #endif
 }