https://github.com/python/cpython/commit/070993b8ad26e6dd0f97d07db19d1400aa613a47
commit: 070993b8ad26e6dd0f97d07db19d1400aa613a47
branch: 3.14
author: Miss Islington (bot) <[email protected]>
committer: ZeroIntensity <[email protected]>
date: 2025-10-07T14:18:15-04:00
summary:

[3.14] gh-135729: Store reference to globals in `Interpreter._decref` 
(GH-139104) (GH-139112)

* gh-135729: Store reference to globals in `Interpreter._decref` (GH-139104)
(cherry picked from commit 571210b8f34a54922e5eb11d65060d7a77b8bdf0)

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

files:
A Misc/NEWS.d/next/Library/2025-09-18-05-32-18.gh-issue-135729.8AmMza.rst
M Lib/concurrent/interpreters/__init__.py
M Lib/test/test_interpreters/test_api.py

diff --git a/Lib/concurrent/interpreters/__init__.py 
b/Lib/concurrent/interpreters/__init__.py
index aa46a2b37a48d5..ea4147ee9a25da 100644
--- a/Lib/concurrent/interpreters/__init__.py
+++ b/Lib/concurrent/interpreters/__init__.py
@@ -149,12 +149,17 @@ def __del__(self):
     def __reduce__(self):
         return (type(self), (self._id,))
 
-    def _decref(self):
+    # gh-135729: Globals might be destroyed by the time this is called, so we
+    # need to keep references ourself
+    def _decref(self, *,
+                InterpreterNotFoundError=InterpreterNotFoundError,
+                _interp_decref=_interpreters.decref,
+                ):
         if not self._ownsref:
             return
         self._ownsref = False
         try:
-            _interpreters.decref(self._id)
+            _interp_decref(self._id)
         except InterpreterNotFoundError:
             pass
 
diff --git a/Lib/test/test_interpreters/test_api.py 
b/Lib/test/test_interpreters/test_api.py
index 3fee98ea93e637..c5a1743e7fdedf 100644
--- a/Lib/test/test_interpreters/test_api.py
+++ b/Lib/test/test_interpreters/test_api.py
@@ -419,6 +419,21 @@ def test_pickle(self):
                 unpickled = pickle.loads(data)
                 self.assertEqual(unpickled, interp)
 
+    @support.requires_subprocess()
+    @force_not_colorized
+    def test_cleanup_in_repl(self):
+        # GH-135729: Using a subinterpreter in the REPL would lead to an 
unraisable
+        # exception during finalization
+        repl = script_helper.spawn_python("-i")
+        script = b"""if True:
+        from concurrent import interpreters
+        interpreters.create()
+        exit()"""
+        stdout, stderr = repl.communicate(script)
+        self.assertIsNone(stderr)
+        self.assertNotIn(b"Traceback", stdout)
+
+
 
 class TestInterpreterIsRunning(TestBase):
 
diff --git 
a/Misc/NEWS.d/next/Library/2025-09-18-05-32-18.gh-issue-135729.8AmMza.rst 
b/Misc/NEWS.d/next/Library/2025-09-18-05-32-18.gh-issue-135729.8AmMza.rst
new file mode 100644
index 00000000000000..1777839a1bf633
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2025-09-18-05-32-18.gh-issue-135729.8AmMza.rst
@@ -0,0 +1,2 @@
+Fix unraisable exception during finalization when using
+:mod:`concurrent.interpreters` in the REPL.

_______________________________________________
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