]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-135729: Store reference to globals in `Interpreter._decref` (GH-139104)
authorPeter Bierma <zintensitydev@gmail.com>
Thu, 18 Sep 2025 11:17:51 +0000 (07:17 -0400)
committerGitHub <noreply@github.com>
Thu, 18 Sep 2025 11:17:51 +0000 (11:17 +0000)
Lib/concurrent/interpreters/__init__.py
Lib/test/test_interpreters/test_api.py
Misc/NEWS.d/next/Library/2025-09-18-05-32-18.gh-issue-135729.8AmMza.rst [new file with mode: 0644]

index aa46a2b37a48d51112a05a0dc69c80530117286d..ea4147ee9a25da554cddc06632e04e620008a6d2 100644 (file)
@@ -149,12 +149,17 @@ class Interpreter:
     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
 
index 3fee98ea93e6377676e387de9b89103e149ed616..1f38a43be51e7a716e5876d80bb9dafde0a55335 100644 (file)
@@ -419,6 +419,22 @@ class InterpreterObjectTests(TestBase):
                 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.assertIn(b"remaining subinterpreters", stdout)
+        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 (file)
index 0000000..1777839
--- /dev/null
@@ -0,0 +1,2 @@
+Fix unraisable exception during finalization when using
+:mod:`concurrent.interpreters` in the REPL.