mirror of
https://github.com/python/cpython.git
synced 2025-08-11 04:19:06 +00:00
gh-109047: concurrent.futures catches PythonFinalizationError (#109810)
concurrent.futures: The *executor manager thread* now catches
exceptions when adding an item to the *call queue*. During Python
finalization, creating a new thread can now raise RuntimeError. Catch
the exception and call terminate_broken() in this case.
Add test_python_finalization_error() to test_concurrent_futures.
concurrent.futures._ExecutorManagerThread changes:
* terminate_broken() no longer calls shutdown_workers() since the
call queue is no longer working anymore (read and write ends of
the queue pipe are closed).
* terminate_broken() now terminates child processes, not only
wait until they complete.
* _ExecutorManagerThread.terminate_broken() now holds shutdown_lock
to prevent race conditons with ProcessPoolExecutor.submit().
multiprocessing.Queue changes:
* Add _terminate_broken() method.
* _start_thread() sets _thread to None on exception to prevent
leaking "dangling threads" even if the thread was not started
yet.
(cherry picked from commit 6351842121
)
This commit is contained in:
parent
41eb0c7286
commit
356de021d7
4 changed files with 90 additions and 17 deletions
|
@ -158,6 +158,15 @@ class Queue(object):
|
|||
except AttributeError:
|
||||
pass
|
||||
|
||||
def _terminate_broken(self):
|
||||
# Close a Queue on error.
|
||||
|
||||
# gh-94777: Prevent queue writing to a pipe which is no longer read.
|
||||
self._reader.close()
|
||||
|
||||
self.close()
|
||||
self.join_thread()
|
||||
|
||||
def _start_thread(self):
|
||||
debug('Queue._start_thread()')
|
||||
|
||||
|
@ -169,13 +178,19 @@ class Queue(object):
|
|||
self._wlock, self._reader.close, self._writer.close,
|
||||
self._ignore_epipe, self._on_queue_feeder_error,
|
||||
self._sem),
|
||||
name='QueueFeederThread'
|
||||
name='QueueFeederThread',
|
||||
daemon=True,
|
||||
)
|
||||
self._thread.daemon = True
|
||||
|
||||
debug('doing self._thread.start()')
|
||||
self._thread.start()
|
||||
debug('... done self._thread.start()')
|
||||
try:
|
||||
debug('doing self._thread.start()')
|
||||
self._thread.start()
|
||||
debug('... done self._thread.start()')
|
||||
except:
|
||||
# gh-109047: During Python finalization, creating a thread
|
||||
# can fail with RuntimeError.
|
||||
self._thread = None
|
||||
raise
|
||||
|
||||
if not self._joincancelled:
|
||||
self._jointhread = Finalize(
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue