Issue #18808: Non-daemon threads are now automatically joined when a sub-interpreter is shutdown (it would previously dump a fatal error).
This commit is contained in:
parent
0bb766b95c
commit
7eaf3f7080
|
@ -9,6 +9,7 @@ import re
|
|||
import sys
|
||||
_thread = import_module('_thread')
|
||||
threading = import_module('threading')
|
||||
import _testcapi
|
||||
import time
|
||||
import unittest
|
||||
import weakref
|
||||
|
@ -754,6 +755,53 @@ class ThreadJoinOnShutdown(BaseTestCase):
|
|||
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.
|
||||
|
|
|
@ -10,6 +10,9 @@ Projected Release date: 2013-09-08
|
|||
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.
|
||||
|
|
|
@ -789,6 +789,9 @@ Py_EndInterpreter(PyThreadState *tstate)
|
|||
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");
|
||||
|
||||
|
|
Loading…
Reference in New Issue