[Python-checkins] cpython: Issue #18808 again: fix the after-fork logic for not-yet-started or

antoine.pitrou python-checkins at python.org
Sun Sep 8 13:19:14 CEST 2013


http://hg.python.org/cpython/rev/74dc664ad699
changeset:   85623:74dc664ad699
user:        Antoine Pitrou <solipsis at pitrou.net>
date:        Sun Sep 08 13:19:06 2013 +0200
summary:
  Issue #18808 again: fix the after-fork logic for not-yet-started or already-stopped threads.
(AFAICT, in theory, we must reset all the locks, not just those in use)

files:
  Lib/test/test_threading.py |   2 +-
  Lib/threading.py           |  16 +++++++---------
  2 files changed, 8 insertions(+), 10 deletions(-)


diff --git a/Lib/test/test_threading.py b/Lib/test/test_threading.py
--- a/Lib/test/test_threading.py
+++ b/Lib/test/test_threading.py
@@ -109,7 +109,7 @@
         if verbose:
             print('waiting for all tasks to complete')
         for t in threads:
-            t.join(NUMTASKS)
+            t.join()
             self.assertTrue(not t.is_alive())
             self.assertNotEqual(t.ident, 0)
             self.assertFalse(t.ident is None)
diff --git a/Lib/threading.py b/Lib/threading.py
--- a/Lib/threading.py
+++ b/Lib/threading.py
@@ -517,8 +517,6 @@
 _active_limbo_lock = _allocate_lock()
 _active = {}    # maps thread id to Thread object
 _limbo = {}
-
-# For debug and leak testing
 _dangling = WeakSet()
 
 # Main class for threads
@@ -552,14 +550,11 @@
         self._tstate_lock = None
         self._started = Event()
         self._stopped = Event()
-        # _is_stopped should be the same as _stopped.is_set().  The bizarre
-        # duplication is to allow test_is_alive_after_fork to pass on old
-        # Linux kernels.  See issue 18808.
-        self._is_stopped = False
         self._initialized = True
         # sys.stderr is not stored in the class like
         # sys.exc_info since it can be changed between instances
         self._stderr = _sys.stderr
+        # For debugging and _after_fork()
         _dangling.add(self)
 
     def _reset_internal_locks(self, is_alive):
@@ -711,7 +706,6 @@
 
     def _stop(self):
         self._stopped.set()
-        self._is_stopped = True
 
     def _delete(self):
         "Remove current thread from the dict of currently running threads."
@@ -798,7 +792,7 @@
         assert self._initialized, "Thread.__init__() not called"
         if not self._started.is_set():
             return False
-        if not self._is_stopped:
+        if not self._stopped.is_set():
             return True
         # The Python part of the thread is done, but the C part may still be
         # waiting to run.
@@ -976,7 +970,11 @@
     current = current_thread()
     _main_thread = current
     with _active_limbo_lock:
-        for thread in _enumerate():
+        # Dangling thread instances must still have their locks reset,
+        # because someone may join() them.
+        threads = set(_enumerate())
+        threads.update(_dangling)
+        for thread in threads:
             # Any lock/condition variable may be currently locked or in an
             # invalid state, so we reinitialize them.
             if thread is current:

-- 
Repository URL: http://hg.python.org/cpython


More information about the Python-checkins mailing list