--- Python-2.6.4/Lib/test/test_thread.py.orig 2010-02-26 15:17:18.000000000 -0500 +++ Python-2.6.4/Lib/test/test_thread.py 2010-02-26 15:16:33.000000000 -0500 @@ -4,7 +4,7 @@ from test import test_support import thread import time - +import sys NUMTASKS = 10 NUMTRIPS = 3 @@ -98,7 +98,55 @@ thread.stack_size(0) +class ForkingThreadTests(BasicThreadTest): + def task(self): + try: + pid = os.fork() + except: + # Child: an exception occurred while forking + os._exit(1) + + if pid: + # Parent: + # The child should have exited immediately, with an exit + # code of 0. If the child is still there or exited with + # an error, then fail. + try: + time.sleep(2) + ret = os.waitpid(pid, os.WNOHANG) + if not os.WIFEXITED(ret[1]): + # Child did not exit cleanly. Kill it and mark test + # as failed + print "Child did not exit" + os.kill(pid, 9) + self.testFailed = True + elif os.WEXITSTATUS(ret[1]): + print "Child exited with error" + self.testFailed = True + finally: + self.done_mutex.release() + else: + # Child, no exception. Exit cleanly. + os._exit(0) + + def test_fork_inside_thread(self): + # Test for issue 7242: Forking in a thread raises RuntimeError. + # Spawn a thread, and inside that thread, call os.fork(). The + # issue is that on some platforms (e.g. Solaris 8, 9) the child + # process raises a RuntimeError with the message "not holding + # the import lock". The child process then hangs. + if sys.platform[:3] == 'win': + from test.test_support import TestSkipped + raise TestSkipped("This test is only appropriate for " + "unix-like systems.") + + self.testFailed = False + thread.start_new_thread(self.task, ()) + self.done_mutex.acquire() + self.assertFalse(self.testFailed, + "Child process did not exit cleanly") + class Barrier: def __init__(self, num_threads): self.num_threads = num_threads @@ -162,7 +210,8 @@ def test_main(): - test_support.run_unittest(ThreadRunningTests, BarrierTest) + test_support.run_unittest(ThreadRunningTests, BarrierTest, + ForkingThreadTests) if __name__ == "__main__": test_main()