63 lines
2.1 KiB
Diff
63 lines
2.1 KiB
Diff
|
|
# HG changeset patch
|
|
# User Charles-François Natali <neologix@free.fr>
|
|
# Date 1328209039 -3600
|
|
# Node ID c3649173d093ce3bb2f887c1b4c3207196f1f453
|
|
# Parent 0b8917fc6db55d371573398c2ae29b120be40a19
|
|
Issue #13817: After fork(), reinit the ad-hoc TLS implementation earlier to fix
|
|
a random deadlock when fork() is called in a multithreaded process in debug
|
|
mode, and make PyOS_AfterFork() more robust.
|
|
|
|
diff --git a/Lib/test/test_threading.py b/Lib/test/test_threading.py
|
|
--- a/Lib/test/test_threading.py
|
|
+++ b/Lib/test/test_threading.py
|
|
@@ -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
|
|
diff --git a/Modules/signalmodule.c b/Modules/signalmodule.c
|
|
--- a/Modules/signalmodule.c
|
|
+++ b/Modules/signalmodule.c
|
|
@@ -976,11 +976,13 @@ 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();
|
|
_PyGILState_Reinit();
|
|
PyEval_ReInitThreads();
|
|
main_thread = PyThread_get_thread_ident();
|
|
main_pid = getpid();
|
|
_PyImport_ReInitLock();
|
|
- PyThread_ReInitTLS();
|
|
#endif
|
|
}
|
|
|