[pypy-commit] pypy py3.5-set-sentinel: release the sentinel lock before the thread dies

plan_rich pypy.commits at gmail.com
Fri Sep 30 10:02:54 EDT 2016


Author: Richard Plangger <planrichi at gmail.com>
Branch: py3.5-set-sentinel
Changeset: r87473:aa01e511c9e8
Date: 2016-09-30 16:02 +0200
http://bitbucket.org/pypy/pypy/changeset/aa01e511c9e8/

Log:	release the sentinel lock before the thread dies

diff --git a/pypy/module/thread/os_lock.py b/pypy/module/thread/os_lock.py
--- a/pypy/module/thread/os_lock.py
+++ b/pypy/module/thread/os_lock.py
@@ -3,6 +3,7 @@
 """
 
 import time
+import weakref
 from rpython.rlib import rthread
 from pypy.module.thread.error import wrap_thread_error
 from pypy.interpreter.baseobjspace import W_Root
@@ -10,6 +11,7 @@
 from pypy.interpreter.typedef import TypeDef, make_weakref_descr
 from pypy.interpreter.error import oefmt
 from rpython.rlib.rarithmetic import r_longlong, ovfcheck, ovfcheck_float_to_longlong
+from rpython.rlib.rthread import ThreadLocalReference
 
 # Force the declaration of the type 'thread.LockType' for RPython
 #import pypy.module.thread.rpython.exttable
@@ -19,6 +21,7 @@
 
 RPY_LOCK_FAILURE, RPY_LOCK_ACQUIRED, RPY_LOCK_INTR = range(3)
 
+
 def parse_acquire_args(space, blocking, timeout):
     if not blocking and timeout != -1.0:
         raise oefmt(space.w_ValueError,
@@ -144,15 +147,24 @@
 See LockType.__doc__ for information about locks."""
     return space.wrap(Lock(space))
 
-def set_sentinel(space):
+tlref_sentinel_lock = ThreadLocalReference(Lock)
+
+def _set_sentinel(space):
     """_set_sentinel() -> lock
 
     Set a sentinel lock that will be released when the current thread 
     state is finalized (after it is untied from the interpreter).
 
     This is a private API for the threading module."""
-    lock = allocate_lock(space)
-    return lock
+    # see issue 18808. We need to release this lock just before exiting
+    # the any thread!
+    lock = Lock(space)
+    # create a weak reference to the lock object and set it
+    # pass save it as a thread local reference
+    # see os_thread.py just before gc_thread_die
+    tlref_sentinel_lock.set(lock)
+    #
+    return space.wrap(lock)
 
 class W_RLock(W_Root):
     def __init__(self, space):
diff --git a/pypy/module/thread/os_thread.py b/pypy/module/thread/os_thread.py
--- a/pypy/module/thread/os_thread.py
+++ b/pypy/module/thread/os_thread.py
@@ -7,6 +7,7 @@
 from pypy.module.thread.error import wrap_thread_error
 from pypy.interpreter.error import OperationError, oefmt
 from pypy.interpreter.gateway import unwrap_spec, Arguments
+from pypy.module.thread.os_lock import tlref_sentinel_lock
 
 # Here are the steps performed to start a new thread:
 #
@@ -102,6 +103,12 @@
                 os.write(STDERR, "\n")
             except OSError:
                 pass
+        # TODO move after rthread.gc_thread_die()?
+        lock = tlref_sentinel_lock.get()
+        if lock and lock.descr_lock_locked(space):
+            lock.descr_lock_release(space)
+            tlref_sentinel_lock.set(None)
+        #
         bootstrapper.nbthreads -= 1
         rthread.gc_thread_die()
     bootstrap = staticmethod(bootstrap)


More information about the pypy-commit mailing list