From b61b818d916942aad1f8f3e33181801c4a1ed14b Mon Sep 17 00:00:00 2001 From: Kyle Stanley Date: Fri, 27 Mar 2020 15:31:22 -0400 Subject: bpo-39812: Remove daemon threads in concurrent.futures (GH-19149) Remove daemon threads from :mod:`concurrent.futures` by adding an internal `threading._register_atexit()`, which calls registered functions prior to joining all non-daemon threads. This allows for compatibility with subinterpreters, which don't support daemon threads. --- Lib/test/test_threading.py | 50 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) (limited to 'Lib/test/test_threading.py') diff --git a/Lib/test/test_threading.py b/Lib/test/test_threading.py index f1037b5d94..da17e1281d 100644 --- a/Lib/test/test_threading.py +++ b/Lib/test/test_threading.py @@ -1397,5 +1397,55 @@ class InterruptMainTests(unittest.TestCase): signal.signal(signal.SIGINT, handler) +class AtexitTests(unittest.TestCase): + + def test_atexit_output(self): + rc, out, err = assert_python_ok("-c", """if True: + import threading + + def run_last(): + print('parrot') + + threading._register_atexit(run_last) + """) + + self.assertFalse(err) + self.assertEqual(out.strip(), b'parrot') + + def test_atexit_called_once(self): + rc, out, err = assert_python_ok("-c", """if True: + import threading + from unittest.mock import Mock + + mock = Mock() + threading._register_atexit(mock) + mock.assert_not_called() + # force early shutdown to ensure it was called once + threading._shutdown() + mock.assert_called_once() + """) + + self.assertFalse(err) + + def test_atexit_after_shutdown(self): + # The only way to do this is by registering an atexit within + # an atexit, which is intended to raise an exception. + rc, out, err = assert_python_ok("-c", """if True: + import threading + + def func(): + pass + + def run_last(): + threading._register_atexit(func) + + threading._register_atexit(run_last) + """) + + self.assertTrue(err) + self.assertIn("RuntimeError: can't register atexit after shutdown", + err.decode()) + + if __name__ == "__main__": unittest.main() -- cgit v1.2.1