Author: Philip Jenvey <[email protected]>
Branch: py3k
Changeset: r61462:91f21023331b
Date: 2013-02-19 11:11 -0800
http://bitbucket.org/pypy/pypy/changeset/91f21023331b/
Log: attempt to fix test_fork.test_nested_import_lock_fork (the test
seems to require translation)
diff --git a/pypy/module/imp/importing.py b/pypy/module/imp/importing.py
--- a/pypy/module/imp/importing.py
+++ b/pypy/module/imp/importing.py
@@ -786,9 +786,18 @@
def reinit_lock(self):
# Called after fork() to ensure that newly created child
# processes do not share locks with the parent
- self.lock = None
- self.lockowner = None
- self.lockcounter = 0
+ if self.lockcounter > 1:
+ # Forked as a side effect of import
+ self.lock = self.space.allocate_lock()
+ me = self.space.getexecutioncontext()
+ self.lock.acquire(True)
+ # XXX: can the previous line fail?
+ self.lockowner = me
+ self.lockcounter -= 1
+ else:
+ self.lock = None
+ self.lockowner = None
+ self.lockcounter = 0
def getimportlock(space):
return space.fromcache(ImportRLock)
diff --git a/pypy/module/thread/test/test_fork.py
b/pypy/module/thread/test/test_fork.py
--- a/pypy/module/thread/test/test_fork.py
+++ b/pypy/module/thread/test/test_fork.py
@@ -1,6 +1,8 @@
from pypy.module.thread.test.support import GenericTestThread
class AppTestFork(GenericTestThread):
+ spaceconfig = dict(usemodules=GenericTestThread.spaceconfig['usemodules']
+ ('imp',))
+
def test_fork_with_thread(self):
# XXX This test depends on a multicore machine, as busy_thread must
# aquire the GIL the instant that the main thread releases it.
@@ -84,3 +86,45 @@
# if 9, process was killed by timer.
# if 42<<8, os._exit(42) was correctly reached.
assert feedback == [42<<8]
+
+ def test_nested_import_lock_fork(self):
+ """Check fork() in main thread works while the main thread is doing an
import"""
+ # Issue 9573: this used to trigger RuntimeError in the child process
+ import imp
+ import os
+ import time
+
+ def fork_with_import_lock(level):
+ release = 0
+ in_child = False
+ try:
+ try:
+ for i in range(level):
+ imp.acquire_lock()
+ release += 1
+ pid = os.fork()
+ in_child = not pid
+ finally:
+ for i in range(release):
+ imp.release_lock()
+ except RuntimeError:
+ if in_child:
+ if verbose > 1:
+ print("RuntimeError in child")
+ os._exit(1)
+ raise
+ if in_child:
+ os._exit(0)
+
+ for i in range(10):
+ spid, status = os.waitpid(pid, os.WNOHANG)
+ if spid == pid:
+ break
+ time.sleep(1.0)
+ assert spid == pid
+ assert status == 0
+
+ # Check this works with various levels of nested
+ # import in the main thread
+ for level in range(5):
+ fork_with_import_lock(level)
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit