diff options
author | Mark Nemec <mrknmc@me.com> | 2018-04-10 17:23:14 (GMT) |
---|---|---|
committer | Antoine Pitrou <pitrou@free.fr> | 2018-04-10 17:23:14 (GMT) |
commit | c4b695f85e141f57d22d8edf7bc2c756da136918 (patch) | |
tree | 73fee6f3f23c9d7b0496a27de71c4ca319b793f6 /Lib/concurrent/futures | |
parent | f178028f37c9dafb72608b719eb03e5a70af4ff5 (diff) | |
download | cpython-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.py | 7 | ||||
-rw-r--r-- | Lib/concurrent/futures/thread.py | 7 |
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) |