Skip to content
This repository was archived by the owner on Nov 23, 2017. It is now read-only.

Commit f9b0d51

Browse files
committed
Fix Gather.cancel() to return True when there were active child tasks.
Patch by Johannes Ebke.
1 parent f5ab2bb commit f9b0d51

File tree

2 files changed

+34
-2
lines changed

2 files changed

+34
-2
lines changed

asyncio/tasks.py

+4-2
Original file line numberDiff line numberDiff line change
@@ -592,9 +592,11 @@ def __init__(self, children, *, loop=None):
592592
def cancel(self):
593593
if self.done():
594594
return False
595+
ret = False
595596
for child in self._children:
596-
child.cancel()
597-
return True
597+
if child.cancel():
598+
ret = True
599+
return ret
598600

599601

600602
def gather(*coros_or_futures, loop=None, return_exceptions=False):

tests/test_tasks.py

+30
Original file line numberDiff line numberDiff line change
@@ -1899,6 +1899,36 @@ def test_cancel_blocking_wait_for(self):
18991899
def test_cancel_wait_for(self):
19001900
self._test_cancel_wait_for(60.0)
19011901

1902+
def test_cancel_gather(self):
1903+
"""Ensure that a gathering future refuses to be cancelled once all
1904+
children are done"""
1905+
loop = asyncio.new_event_loop()
1906+
self.addCleanup(loop.close)
1907+
1908+
fut = asyncio.Future(loop=loop)
1909+
# The indirection fut->child_coro is needed since otherwise the
1910+
# gathering task is done at the same time as the child future
1911+
def child_coro():
1912+
return (yield from fut)
1913+
gather_future = asyncio.gather(child_coro(), loop=loop)
1914+
gather_task = asyncio.ensure_future(gather_future, loop=loop)
1915+
1916+
cancel_result = None
1917+
def cancelling_callback(_):
1918+
nonlocal cancel_result
1919+
cancel_result = gather_task.cancel()
1920+
fut.add_done_callback(cancelling_callback)
1921+
1922+
fut.set_result(42) # calls the cancelling_callback after fut is done()
1923+
1924+
# At this point the task should complete.
1925+
loop.run_until_complete(gather_task)
1926+
1927+
# Python issue #26923: asyncio.gather drops cancellation
1928+
self.assertEqual(cancel_result, False)
1929+
self.assertFalse(gather_task.cancelled())
1930+
self.assertEqual(gather_task.result(), [42])
1931+
19021932

19031933
class GatherTestsBase:
19041934

0 commit comments

Comments
 (0)