Skip to content

Commit c447ba0

Browse files
committed
Issue #23140, asyncio: Fix cancellation of Process.wait(). Check the state of
the waiter future before setting its result.
1 parent 8c1a4a2 commit c447ba0

File tree

2 files changed

+30
-1
lines changed

2 files changed

+30
-1
lines changed

Lib/asyncio/subprocess.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,8 @@ def process_exited(self):
9696
returncode = self._transport.get_returncode()
9797
while self._waiters:
9898
waiter = self._waiters.popleft()
99-
waiter.set_result(returncode)
99+
if not waiter.cancelled():
100+
waiter.set_result(returncode)
100101

101102

102103
class Process:

Lib/test/test_asyncio/test_subprocess.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,34 @@ def len_message(message):
223223
self.assertEqual(output.rstrip(), b'3')
224224
self.assertEqual(exitcode, 0)
225225

226+
def test_cancel_process_wait(self):
227+
# Issue #23140: cancel Process.wait()
228+
229+
@asyncio.coroutine
230+
def wait_proc(proc, event):
231+
event.set()
232+
yield from proc.wait()
233+
234+
@asyncio.coroutine
235+
def cancel_wait():
236+
proc = yield from asyncio.create_subprocess_exec(
237+
*PROGRAM_BLOCKED,
238+
loop=self.loop)
239+
240+
# Create an internal future waiting on the process exit
241+
event = asyncio.Event(loop=self.loop)
242+
task = self.loop.create_task(wait_proc(proc, event))
243+
yield from event.wait()
244+
245+
# Cancel the future
246+
task.cancel()
247+
248+
# Kill the process and wait until it is done
249+
proc.kill()
250+
yield from proc.wait()
251+
252+
self.loop.run_until_complete(cancel_wait())
253+
226254

227255
if sys.platform != 'win32':
228256
# Unix

0 commit comments

Comments
 (0)