https://github.com/python/cpython/commit/8f4121168a1e243bf10615011913b785a6a00f12
commit: 8f4121168a1e243bf10615011913b785a6a00f12
branch: 3.13
author: Miss Islington (bot) <[email protected]>
committer: ZeroIntensity <[email protected]>
date: 2025-07-25T15:14:27Z
summary:

[3.13] gh-130522: Fix unraisable TypeError in threading at interpreter shutdown 
(GH-131537) (GH-137106)

gh-130522: Fix unraisable TypeError in threading at interpreter shutdown 
(GH-131537)
(cherry picked from commit cb93b6fc5ea525f8075cb53ec373356fec63903a)

Co-authored-by: Tyler Kennedy <[email protected]>
Co-authored-by: Peter Bierma <[email protected]>

files:
A Misc/NEWS.d/next/Library/2025-07-25-09-21-56.gh-issue-130522.Crwq68.rst
M Lib/test/test_threading.py
M Lib/threading.py

diff --git a/Lib/test/test_threading.py b/Lib/test/test_threading.py
index 9ba5f68fd4a53c..3ed7fdb3fabde6 100644
--- a/Lib/test/test_threading.py
+++ b/Lib/test/test_threading.py
@@ -1849,6 +1849,23 @@ def modify_file():
             t.start()
             t.join()
 
+    def test_dummy_thread_on_interpreter_shutdown(self):
+        # GH-130522: When `threading` held a reference to itself and then a
+        # _DummyThread() object was created, destruction of the dummy thread
+        # would emit an unraisable exception at shutdown, due to a lock being
+        # destroyed.
+        code = """if True:
+        import sys
+        import threading
+
+        threading.x = sys.modules[__name__]
+        x = threading._DummyThread()
+        """
+        rc, out, err = assert_python_ok("-c", code)
+        self.assertEqual(rc, 0)
+        self.assertEqual(out, b"")
+        self.assertEqual(err, b"")
+
 
 class ThreadRunFail(threading.Thread):
     def run(self):
diff --git a/Lib/threading.py b/Lib/threading.py
index 11f1b5af6ac1b3..acf5090716c9be 100644
--- a/Lib/threading.py
+++ b/Lib/threading.py
@@ -1381,7 +1381,7 @@ def __init__(self, dummy_thread):
         # the related _DummyThread will be kept forever!
         _thread_local_info._track_dummy_thread_ref = self
 
-    def __del__(self):
+    def __del__(self, _active_limbo_lock=_active_limbo_lock, _active=_active):
         with _active_limbo_lock:
             if _active.get(self._tident) is self._dummy_thread:
                 _active.pop(self._tident, None)
diff --git 
a/Misc/NEWS.d/next/Library/2025-07-25-09-21-56.gh-issue-130522.Crwq68.rst 
b/Misc/NEWS.d/next/Library/2025-07-25-09-21-56.gh-issue-130522.Crwq68.rst
new file mode 100644
index 00000000000000..6c2246631dda9e
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2025-07-25-09-21-56.gh-issue-130522.Crwq68.rst
@@ -0,0 +1,2 @@
+Fix unraisable :exc:`TypeError` raised during :term:`interpreter shutdown`
+in the :mod:`threading` module.

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]

Reply via email to