summaryrefslogtreecommitdiffstats
path: root/Lib
diff options
context:
space:
mode:
authorVictor Stinner <vstinner@redhat.com>2019-06-13 10:06:24 (GMT)
committerGitHub <noreply@github.com>2019-06-13 10:06:24 (GMT)
commit6f75c873752a16a7ad8f35855b1e29f59d048e84 (patch)
treec3df13f3339045c40d4335c64a8e37c3774c3b99 /Lib
parentb4b814b3988abf69f07f8492d82e855c51b2a75d (diff)
downloadcpython-6f75c873752a16a7ad8f35855b1e29f59d048e84.zip
cpython-6f75c873752a16a7ad8f35855b1e29f59d048e84.tar.gz
cpython-6f75c873752a16a7ad8f35855b1e29f59d048e84.tar.bz2
tbpo-36402: Fix threading.Thread._stop() (GH-14047)
Remove the _tstate_lock from _shutdown_locks, don't remove None.
Diffstat (limited to 'Lib')
-rw-r--r--Lib/test/test_threading.py24
-rw-r--r--Lib/threading.py2
2 files changed, 25 insertions, 1 deletions
diff --git a/Lib/test/test_threading.py b/Lib/test/test_threading.py
index ad90010..0a0a62b 100644
--- a/Lib/test/test_threading.py
+++ b/Lib/test/test_threading.py
@@ -738,6 +738,30 @@ class ThreadTests(BaseTestCase):
finally:
sys.settrace(old_trace)
+ @cpython_only
+ def test_shutdown_locks(self):
+ for daemon in (False, True):
+ with self.subTest(daemon=daemon):
+ event = threading.Event()
+ thread = threading.Thread(target=event.wait, daemon=daemon)
+
+ # Thread.start() must add lock to _shutdown_locks,
+ # but only for non-daemon thread
+ thread.start()
+ tstate_lock = thread._tstate_lock
+ if not daemon:
+ self.assertIn(tstate_lock, threading._shutdown_locks)
+ else:
+ self.assertNotIn(tstate_lock, threading._shutdown_locks)
+
+ # unblock the thread and join it
+ event.set()
+ thread.join()
+
+ # Thread._stop() must remove tstate_lock from _shutdown_locks.
+ # Daemon threads must never add it to _shutdown_locks.
+ self.assertNotIn(tstate_lock, threading._shutdown_locks)
+
class ThreadJoinOnShutdown(BaseTestCase):
diff --git a/Lib/threading.py b/Lib/threading.py
index 6792640..7c6d404 100644
--- a/Lib/threading.py
+++ b/Lib/threading.py
@@ -965,7 +965,7 @@ class Thread:
self._tstate_lock = None
if not self.daemon:
with _shutdown_locks_lock:
- _shutdown_locks.discard(self._tstate_lock)
+ _shutdown_locks.discard(lock)
def _delete(self):
"Remove current thread from the dict of currently running threads."