summaryrefslogtreecommitdiffstats
path: root/Lib/test/test_threading.py
diff options
context:
space:
mode:
Diffstat (limited to 'Lib/test/test_threading.py')
-rw-r--r--Lib/test/test_threading.py75
1 files changed, 74 insertions, 1 deletions
diff --git a/Lib/test/test_threading.py b/Lib/test/test_threading.py
index bd019cd..0a78f8c 100644
--- a/Lib/test/test_threading.py
+++ b/Lib/test/test_threading.py
@@ -9,6 +9,7 @@ import re
import sys
_thread = import_module('_thread')
threading = import_module('threading')
+import _testcapi
import time
import unittest
import weakref
@@ -473,7 +474,7 @@ class ThreadJoinOnShutdown(BaseTestCase):
# problems with some operating systems (issue #3863): skip problematic tests
# on platforms known to behave badly.
platforms_to_skip = ('freebsd4', 'freebsd5', 'freebsd6', 'netbsd5',
- 'os2emx', 'hp-ux11')
+ 'hp-ux11')
def _run_and_join(self, script):
script = """if 1:
@@ -749,6 +750,78 @@ class ThreadJoinOnShutdown(BaseTestCase):
for t in threads:
t.join()
+ @unittest.skipUnless(hasattr(os, 'fork'), "needs os.fork()")
+ def test_clear_threads_states_after_fork(self):
+ # Issue #17094: check that threads states are cleared after fork()
+
+ # start a bunch of threads
+ threads = []
+ for i in range(16):
+ t = threading.Thread(target=lambda : time.sleep(0.3))
+ threads.append(t)
+ t.start()
+
+ pid = os.fork()
+ if pid == 0:
+ # check that threads states have been cleared
+ if len(sys._current_frames()) == 1:
+ os._exit(0)
+ else:
+ os._exit(1)
+ else:
+ _, status = os.waitpid(pid, 0)
+ self.assertEqual(0, status)
+
+ for t in threads:
+ 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