summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAntoine Pitrou <solipsis@pitrou.net>2013-09-08 11:19:06 (GMT)
committerAntoine Pitrou <solipsis@pitrou.net>2013-09-08 11:19:06 (GMT)
commit5da7e7959e6d3032a564eea68746e03764ed2f68 (patch)
treeaf901dac5b86423cde3d47e6a662fe113d19720c
parent6f6f4865d138f2348889ccc08aa8b18ca0263e48 (diff)
downloadcpython-5da7e7959e6d3032a564eea68746e03764ed2f68.zip
cpython-5da7e7959e6d3032a564eea68746e03764ed2f68.tar.gz
cpython-5da7e7959e6d3032a564eea68746e03764ed2f68.tar.bz2
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)
-rw-r--r--Lib/test/test_threading.py2
-rw-r--r--Lib/threading.py16
2 files changed, 8 insertions, 10 deletions
diff --git a/Lib/test/test_threading.py b/Lib/test/test_threading.py
index 79b10ed..58b0b4e 100644
--- a/Lib/test/test_threading.py
+++ b/Lib/test/test_threading.py
@@ -109,7 +109,7 @@ class ThreadTests(BaseTestCase):
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
index 4d3c6f6..b4b73a8 100644
--- a/Lib/threading.py
+++ b/Lib/threading.py
@@ -517,8 +517,6 @@ def _newname(template="Thread-%d"):
_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 @@ class Thread:
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 @@ class Thread:
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 @@ class Thread:
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 @@ def _after_fork():
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: