[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