summaryrefslogtreecommitdiffstats
path: root/Lib/concurrent/futures
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/concurrent/futures
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/concurrent/futures')
-rw-r--r--Lib/concurrent/futures/process.py7
-rw-r--r--Lib/concurrent/futures/thread.py7
2 files changed, 14 insertions, 0 deletions
diff --git a/Lib/concurrent/futures/process.py b/Lib/concurrent/futures/process.py
index 63f22cf..ce7d642 100644
--- a/Lib/concurrent/futures/process.py
+++ b/Lib/concurrent/futures/process.py
@@ -423,6 +423,10 @@ def _queue_management_worker(executor_reference,
# - The executor that owns this worker has been shutdown.
if shutting_down():
try:
+ # Flag the executor as shutting down as early as possible if it
+ # is not gc-ed yet.
+ if executor is not None:
+ executor._shutdown_thread = True
# Since no new work items can be added, it is safe to shutdown
# this thread if there are no pending work items.
if not pending_work_items:
@@ -595,6 +599,9 @@ class ProcessPoolExecutor(_base.Executor):
raise BrokenProcessPool(self._broken)
if self._shutdown_thread:
raise RuntimeError('cannot schedule new futures after shutdown')
+ if _global_shutdown:
+ raise RuntimeError('cannot schedule new futures after '
+ 'interpreter shutdown')
f = _base.Future()
w = _WorkItem(f, fn, args, kwargs)
diff --git a/Lib/concurrent/futures/thread.py b/Lib/concurrent/futures/thread.py
index 6e22950..b65dee1 100644
--- a/Lib/concurrent/futures/thread.py
+++ b/Lib/concurrent/futures/thread.py
@@ -87,6 +87,10 @@ def _worker(executor_reference, work_queue, initializer, initargs):
# - The executor that owns the worker has been collected OR
# - The executor that owns the worker has been shutdown.
if _shutdown or executor is None or executor._shutdown:
+ # Flag the executor as shutting down as early as possible if it
+ # is not gc-ed yet.
+ if executor is not None:
+ executor._shutdown = True
# Notice other workers
work_queue.put(None)
return
@@ -145,6 +149,9 @@ class ThreadPoolExecutor(_base.Executor):
if self._shutdown:
raise RuntimeError('cannot schedule new futures after shutdown')
+ if _shutdown:
+ raise RuntimeError('cannot schedule new futures after'
+ 'interpreter shutdown')
f = _base.Future()
w = _WorkItem(f, fn, args, kwargs)