summaryrefslogtreecommitdiffstats
path: root/Lib/concurrent/futures/process.py
diff options
context:
space:
mode:
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>2023-10-02 14:56:09 (GMT)
committerGitHub <noreply@github.com>2023-10-02 14:56:09 (GMT)
commit1d8c18c39df9ab2a66151041aedb41e450779d96 (patch)
treeef2ecc269ecaefec8d4ef8576b71773c7dab73b4 /Lib/concurrent/futures/process.py
parent3e1c9e8264ad9acfef60b3aa9b3aa59bee5becca (diff)
downloadcpython-1d8c18c39df9ab2a66151041aedb41e450779d96.zip
cpython-1d8c18c39df9ab2a66151041aedb41e450779d96.tar.gz
cpython-1d8c18c39df9ab2a66151041aedb41e450779d96.tar.bz2
[3.12] gh-107219: Fix concurrent.futures terminate_broken() (GH-109244) (#109254)
gh-107219: Fix concurrent.futures terminate_broken() (GH-109244) Fix a race condition in concurrent.futures. When a process in the process pool was terminated abruptly (while the future was running or pending), close the connection write end. If the call queue is blocked on sending bytes to a worker process, closing the connection write end interrupts the send, so the queue can be closed. Changes: * _ExecutorManagerThread.terminate_broken() now closes call_queue._writer. * multiprocessing PipeConnection.close() now interrupts WaitForMultipleObjects() in _send_bytes() by cancelling the overlapped operation. (cherry picked from commit a9b1f84790e977fb09f75b148c4c4f5924a6ef99) Co-authored-by: Victor Stinner <vstinner@python.org>
Diffstat (limited to 'Lib/concurrent/futures/process.py')
-rw-r--r--Lib/concurrent/futures/process.py4
1 files changed, 4 insertions, 0 deletions
diff --git a/Lib/concurrent/futures/process.py b/Lib/concurrent/futures/process.py
index 301207f..a8dab13 100644
--- a/Lib/concurrent/futures/process.py
+++ b/Lib/concurrent/futures/process.py
@@ -503,6 +503,10 @@ class _ExecutorManagerThread(threading.Thread):
# https://github.com/python/cpython/issues/94777
self.call_queue._reader.close()
+ # gh-107219: Close the connection writer which can unblock
+ # Queue._feed() if it was stuck in send_bytes().
+ self.call_queue._writer.close()
+
# clean up resources
self.join_executor_internals()