[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