summaryrefslogtreecommitdiffstats
path: root/Lib/test/test_concurrent_futures.py
diff options
context:
space:
mode:
authorMark Nemec <mrknmc@me.com>2018-04-10 17:23:14 (GMT)
committerAntoine Pitrou <pitrou@free.fr>2018-04-10 17:23:14 (GMT)
commitc4b695f85e141f57d22d8edf7bc2c756da136918 (patch)
tree73fee6f3f23c9d7b0496a27de71c4ca319b793f6 /Lib/test/test_concurrent_futures.py
parentf178028f37c9dafb72608b719eb03e5a70af4ff5 (diff)
downloadcpython-c4b695f85e141f57d22d8edf7bc2c756da136918.zip
cpython-c4b695f85e141f57d22d8edf7bc2c756da136918.tar.gz
cpython-c4b695f85e141f57d22d8edf7bc2c756da136918.tar.bz2
bpo-33097: Fix submit accepting callable after executor shutdown by interpreter exit (GH-6144)
Executors in concurrent.futures accepted tasks after executor was shutdown by interpreter exit. Tasks were left in PENDING state forever. This fix changes submit to instead raise a RuntimeError.
Diffstat (limited to 'Lib/test/test_concurrent_futures.py')
-rw-r--r--Lib/test/test_concurrent_futures.py28
1 files changed, 28 insertions, 0 deletions
diff --git a/Lib/test/test_concurrent_futures.py b/Lib/test/test_concurrent_futures.py
index 18d0265..b258a0e 100644
--- a/Lib/test/test_concurrent_futures.py
+++ b/Lib/test/test_concurrent_futures.py
@@ -303,6 +303,34 @@ class ExecutorShutdownTest:
self.assertFalse(err)
self.assertEqual(out.strip(), b"apple")
+ def test_submit_after_interpreter_shutdown(self):
+ # Test the atexit hook for shutdown of worker threads and processes
+ rc, out, err = assert_python_ok('-c', """if 1:
+ import atexit
+ @atexit.register
+ def run_last():
+ try:
+ t.submit(id, None)
+ except RuntimeError:
+ print("runtime-error")
+ raise
+ from concurrent.futures import {executor_type}
+ if __name__ == "__main__":
+ context = '{context}'
+ if not context:
+ t = {executor_type}(5)
+ else:
+ from multiprocessing import get_context
+ context = get_context(context)
+ t = {executor_type}(5, mp_context=context)
+ t.submit(id, 42).result()
+ """.format(executor_type=self.executor_type.__name__,
+ context=getattr(self, "ctx", "")))
+ # Errors in atexit hooks don't change the process exit code, check
+ # stderr manually.
+ self.assertIn("RuntimeError: cannot schedule new futures", err.decode())
+ self.assertEqual(out.strip(), b"runtime-error")
+
def test_hang_issue12364(self):
fs = [self.executor.submit(time.sleep, 0.1) for _ in range(50)]
self.executor.shutdown()