[3.8] bpo-32751: Wait for task cancel in asyncio.wait_for() when time… · python/cpython@57b6988 (original) (raw)

3 files changed

lines changed

Original file line number Diff line number Diff line change
@@ -460,8 +460,13 @@ async def wait_for(fut, timeout, *, loop=None):
460 460 if fut.done():
461 461 return fut.result()
462 462
463 -fut.cancel()
464 -raise exceptions.TimeoutError()
463 +await _cancel_and_wait(fut, loop=loop)
464 +try:
465 +fut.result()
466 +except exceptions.CancelledError as exc:
467 +raise exceptions.TimeoutError() from exc
468 +else:
469 +raise exceptions.TimeoutError()
465 470
466 471 waiter = loop.create_future()
467 472 timeout_handle = loop.call_later(timeout, _release_waiter, waiter)
Original file line number Diff line number Diff line change
@@ -888,6 +888,9 @@ async def inner():
888 888 nonlocal task_done
889 889 try:
890 890 await asyncio.sleep(0.2)
891 +except asyncio.CancelledError:
892 +await asyncio.sleep(0.1)
893 +raise
891 894 finally:
892 895 task_done = True
893 896
@@ -900,6 +903,34 @@ async def inner():
900 903
901 904 loop.run_until_complete(foo())
902 905
906 +def test_wait_for_waits_for_task_cancellation_w_timeout_0(self):
907 +loop = asyncio.new_event_loop()
908 +self.addCleanup(loop.close)
909 +
910 +task_done = False
911 +
912 +async def foo():
913 +async def inner():
914 +nonlocal task_done
915 +try:
916 +await asyncio.sleep(10)
917 +except asyncio.CancelledError:
918 +await asyncio.sleep(0.1)
919 +raise
920 +finally:
921 +task_done = True
922 +
923 +inner_task = self.new_task(loop, inner())
924 +await asyncio.sleep(0.1)
925 +await asyncio.wait_for(inner_task, timeout=0)
926 +
927 +with self.assertRaises(asyncio.TimeoutError) as cm:
928 +loop.run_until_complete(foo())
929 +
930 +self.assertTrue(task_done)
931 +chained = cm.exception.__context__
932 +self.assertEqual(type(chained), asyncio.CancelledError)
933 +
903 934 def test_wait_for_self_cancellation(self):
904 935 loop = asyncio.new_event_loop()
905 936 self.addCleanup(loop.close)
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
1 +When cancelling the task due to a timeout, :meth:`asyncio.wait_for` will now
2 +wait until the cancellation is complete also in the case when *timeout* is
3 +<= 0, like it does with positive timeouts.