(original) (raw)
changeset: 74730:7b24dd587a7b branch: 3.2 parent: 74722:a55ffb6c1993 user: Charles-François Natali neologix@free.fr date: Thu Feb 02 20:31:42 2012 +0100 files: Lib/test/test_threading.py Modules/signalmodule.c description: 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 -r a55ffb6c1993 -r 7b24dd587a7b Lib/test/test_threading.py --- a/Lib/test/test_threading.py Thu Feb 02 16:40:52 2012 +0100 +++ b/Lib/test/test_threading.py Thu Feb 02 20:31:42 2012 +0100 @@ -666,6 +666,29 @@ rc, out, err = assert_python_ok('-c', script) self.assertFalse(err) + @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 -r a55ffb6c1993 -r 7b24dd587a7b Modules/signalmodule.c --- a/Modules/signalmodule.c Thu Feb 02 16:40:52 2012 +0100 +++ b/Modules/signalmodule.c Thu Feb 02 20:31:42 2012 +0100 @@ -991,11 +991,13 @@ 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 } /neologix@free.fr