[Python-checkins] cpython: Issue #18808: Non-daemon threads are now automatically joined when a

antoine.pitrou python-checkins at python.org
Sun Aug 25 19:48:37 CEST 2013


http://hg.python.org/cpython/rev/becbb65074e1
changeset:   85398:becbb65074e1
parent:      85396:2f688a51b37b
user:        Antoine Pitrou <solipsis at pitrou.net>
date:        Sun Aug 25 19:48:18 2013 +0200
summary:
  Issue #18808: Non-daemon threads are now automatically joined when a sub-interpreter is shutdown (it would previously dump a fatal error).

files:
  Lib/test/test_threading.py |  48 ++++++++++++++++++++++++++
  Misc/NEWS                  |   3 +
  Python/pythonrun.c         |   3 +
  3 files changed, 54 insertions(+), 0 deletions(-)


diff --git a/Lib/test/test_threading.py b/Lib/test/test_threading.py
--- a/Lib/test/test_threading.py
+++ b/Lib/test/test_threading.py
@@ -9,6 +9,7 @@
 import sys
 _thread = import_module('_thread')
 threading = import_module('threading')
+import _testcapi
 import time
 import unittest
 import weakref
@@ -754,6 +755,53 @@
             t.join()
 
 
+class SubinterpThreadingTests(BaseTestCase):
+
+    def test_threads_join(self):
+        # Non-daemon threads should be joined at subinterpreter shutdown
+        # (issue #18808)
+        r, w = os.pipe()
+        self.addCleanup(os.close, r)
+        self.addCleanup(os.close, w)
+        code = r"""if 1:
+            import os
+            import threading
+            import time
+
+            def f():
+                # Sleep a bit so that the thread is still running when
+                # Py_EndInterpreter is called.
+                time.sleep(0.05)
+                os.write(%d, b"x")
+            threading.Thread(target=f).start()
+            """ % (w,)
+        ret = _testcapi.run_in_subinterp(code)
+        self.assertEqual(ret, 0)
+        # The thread was joined properly.
+        self.assertEqual(os.read(r, 1), b"x")
+
+    def test_daemon_threads_fatal_error(self):
+        subinterp_code = r"""if 1:
+            import os
+            import threading
+            import time
+
+            def f():
+                # Make sure the daemon thread is still running when
+                # Py_EndInterpreter is called.
+                time.sleep(10)
+            threading.Thread(target=f, daemon=True).start()
+            """
+        script = r"""if 1:
+            import _testcapi
+
+            _testcapi.run_in_subinterp(%r)
+            """ % (subinterp_code,)
+        rc, out, err = assert_python_failure("-c", script)
+        self.assertIn("Fatal Python error: Py_EndInterpreter: "
+                      "not the last thread", err.decode())
+
+
 class ThreadingExceptionTests(BaseTestCase):
     # A RuntimeError should be raised if Thread.start() is called
     # multiple times.
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -10,6 +10,9 @@
 Core and Builtins
 -----------------
 
+- Issue #18808: Non-daemon threads are now automatically joined when
+  a sub-interpreter is shutdown (it would previously dump a fatal error).
+
 - Remove supporting for compiling on systems without getcwd().
 
 - Issue #18774: Remove last bits of GNU PTH thread code and thread_pth.h.
diff --git a/Python/pythonrun.c b/Python/pythonrun.c
--- a/Python/pythonrun.c
+++ b/Python/pythonrun.c
@@ -789,6 +789,9 @@
         Py_FatalError("Py_EndInterpreter: thread is not current");
     if (tstate->frame != NULL)
         Py_FatalError("Py_EndInterpreter: thread still has a frame");
+
+    wait_for_thread_shutdown();
+
     if (tstate != interp->tstate_head || tstate->next != NULL)
         Py_FatalError("Py_EndInterpreter: not the last thread");
 

-- 
Repository URL: http://hg.python.org/cpython


More information about the Python-checkins mailing list