[pypy-svn] r64097 - in pypy/trunk/pypy: module/thread/test rpython/module

iko at codespeak.net iko at codespeak.net
Wed Apr 15 15:56:09 CEST 2009


Author: iko
Date: Wed Apr 15 15:56:07 2009
New Revision: 64097

Added:
   pypy/trunk/pypy/module/thread/test/test_fork.py
Modified:
   pypy/trunk/pypy/rpython/module/ll_os.py
Log:
(iko, tismer, samuele around)

os.fork() would release the GIL before doing the syscall resulting in
a race condition if there were other threads in the parent process. If
another thread grabbed the GIL after it was released but before the
fork() syscall happened, the child process would hang trying to aquire
the GIL.

So:
 - don't release the GIL when doing fork()
 - add a test that will fail more, but not completely, reliably



Added: pypy/trunk/pypy/module/thread/test/test_fork.py
==============================================================================
--- (empty file)
+++ pypy/trunk/pypy/module/thread/test/test_fork.py	Wed Apr 15 15:56:07 2009
@@ -0,0 +1,30 @@
+from pypy.conftest import gettestobjspace
+
+class AppTestFork(object):
+    def setup_class(cls):
+        space = gettestobjspace(usemodules=('thread', 'time'))
+        cls.space = space
+
+    def test_fork(self):
+        # XXX This test depends on a multicore machine, as busy_thread must
+        # aquire the GIL the instant that the main thread releases it.
+        # It will incorrectly pass if the GIL is not grabbed in time.
+        import thread
+        import os
+        import time
+        
+        def busy_thread():
+            while True:
+                time.sleep(0)
+
+        thread.start_new(busy_thread, ())
+
+        pid = os.fork()
+
+        if pid == 0:
+            os._exit(0)
+
+        else:
+            time.sleep(1)
+            spid, status = os.waitpid(pid, os.WNOHANG)
+            assert spid == pid

Modified: pypy/trunk/pypy/rpython/module/ll_os.py
==============================================================================
--- pypy/trunk/pypy/rpython/module/ll_os.py	(original)
+++ pypy/trunk/pypy/rpython/module/ll_os.py	Wed Apr 15 15:56:07 2009
@@ -1234,7 +1234,8 @@
         eci = self.gcc_profiling_bug_workaround('pid_t _noprof_fork(void)',
                                                 'return fork();')
         os_fork = self.llexternal('_noprof_fork', [], rffi.PID_T,
-                                  compilation_info = eci)
+                                  compilation_info = eci,
+                                  threadsafe = False)
 
         def fork_llimpl():
             childpid = rffi.cast(lltype.Signed, os_fork())



More information about the Pypy-commit mailing list