[pypy-svn] r77957 - in pypy/branch/fast-forward/pypy/module: posix thread
afa at codespeak.net
afa at codespeak.net
Thu Oct 14 21:10:43 CEST 2010
Author: afa
Date: Thu Oct 14 21:10:17 2010
New Revision: 77957
Modified:
pypy/branch/fast-forward/pypy/module/posix/interp_posix.py
pypy/branch/fast-forward/pypy/module/thread/__init__.py
pypy/branch/fast-forward/pypy/module/thread/gil.py
pypy/branch/fast-forward/pypy/module/thread/os_thread.py
Log:
Add infrastructure for hooks around os.fork():
'before', 'parent', and 'child'.
Use it to reinit the thread.bootstrap lock,
and the threadlocals structure as well which seems initialized at the
same time.
This fixes the previous test, and helps test_multiprocessing a lot.
Modified: pypy/branch/fast-forward/pypy/module/posix/interp_posix.py
==============================================================================
--- pypy/branch/fast-forward/pypy/module/posix/interp_posix.py (original)
+++ pypy/branch/fast-forward/pypy/module/posix/interp_posix.py Thu Oct 14 21:10:17 2010
@@ -473,7 +473,7 @@
return True
def get(space):
- return space.fromcache(State)
+ return space.fromcache(State)
def _convertenviron(space, w_env):
space.call_method(w_env, 'clear')
@@ -600,11 +600,48 @@
return space.wrap(result)
readlink.unwrap_spec = [ObjSpace, str]
+before_fork_hooks = []
+after_fork_child_hooks = []
+after_fork_parent_hooks = []
+
+ at specialize.memo()
+def get_fork_hooks(where):
+ if where == 'before':
+ return before_fork_hooks
+ elif where == 'child':
+ return after_fork_child_hooks
+ elif where == 'parent':
+ return after_fork_parent_hooks
+ else:
+ assert False, "Unknown fork hook"
+
+def add_fork_hook(where, hook):
+ "NOT_RPYTHON"
+ get_fork_hooks(where).append(hook)
+
+ at specialize.arg(0)
+def run_fork_hooks(where, space):
+ for hook in get_fork_hooks(where):
+ hook(space)
+
def fork(space):
+ run_fork_hooks('before', space)
+
try:
pid = os.fork()
- except OSError, e:
- raise wrap_oserror(space, e)
+ except OSError, e:
+ try:
+ run_fork_hooks('parent', space)
+ except:
+ # Don't clobber the OSError if the fork failed
+ pass
+ raise wrap_oserror(space, e)
+
+ if pid == 0:
+ run_fork_hooks('child', space)
+ else:
+ run_fork_hooks('parent', space)
+
return space.wrap(pid)
def openpty(space):
Modified: pypy/branch/fast-forward/pypy/module/thread/__init__.py
==============================================================================
--- pypy/branch/fast-forward/pypy/module/thread/__init__.py (original)
+++ pypy/branch/fast-forward/pypy/module/thread/__init__.py Thu Oct 14 21:10:17 2010
@@ -29,3 +29,8 @@
space.threadlocals = gil.GILThreadLocals()
space.threadlocals.initialize(space)
space.threadlocals.setvalue(prev)
+
+ from pypy.module.posix.interp_posix import add_fork_hook
+ from pypy.module.thread.os_thread import reinit_threads
+ add_fork_hook('child', reinit_threads)
+
Modified: pypy/branch/fast-forward/pypy/module/thread/gil.py
==============================================================================
--- pypy/branch/fast-forward/pypy/module/thread/gil.py (original)
+++ pypy/branch/fast-forward/pypy/module/thread/gil.py Thu Oct 14 21:10:17 2010
@@ -48,6 +48,12 @@
invoke_around_extcall(before_external_call, after_external_call)
return result
+ def reinit_threads(self, space):
+ if self.ll_GIL:
+ self.ll_GIL = thread.allocate_ll_lock()
+ thread.acquire_NOAUTO(self.ll_GIL, True)
+ self.enter_thread(space)
+
def yield_thread(self):
thread.yield_thread() # explicitly release the gil (used by test_gil)
Modified: pypy/branch/fast-forward/pypy/module/thread/os_thread.py
==============================================================================
--- pypy/branch/fast-forward/pypy/module/thread/os_thread.py (original)
+++ pypy/branch/fast-forward/pypy/module/thread/os_thread.py Thu Oct 14 21:10:17 2010
@@ -67,13 +67,17 @@
args = None
w_callable = None
+ @staticmethod
def setup(space):
if bootstrapper.lock is None:
try:
bootstrapper.lock = thread.allocate_lock()
except thread.error:
raise wrap_thread_error(space, "can't allocate bootstrap lock")
- setup = staticmethod(setup)
+
+ @staticmethod
+ def reinit(space):
+ bootstrapper.lock = None
def bootstrap():
# Note that when this runs, we already hold the GIL. This is ensured
@@ -135,6 +139,17 @@
space.threadlocals.setup_threads(space)
bootstrapper.setup(space)
+def reinit_threads(space):
+ "Called in the child process after a fork()"
+ space.threadlocals.reinit_threads(space)
+ bootstrapper.reinit(space)
+
+ # Clean the threading module after a fork()
+ w_modules = space.sys.get('modules')
+ w_threading = space.finditem_str(w_modules, 'threading')
+ if w_threading is not None:
+ space.call_method(w_threading, "_after_fork")
+
def start_new_thread(space, w_callable, w_args, w_kwargs=NoneNotWrapped):
"""Start a new thread and return its identifier. The thread will call the
More information about the Pypy-commit
mailing list