mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 05:31:20 +00:00 
			
		
		
		
	bpo-37658: Fix asyncio.wait_for() to respect waited task status (GH-21894) (GH-21964)
Currently, if `asyncio.wait_for()` itself is cancelled it will always
raise `CancelledError` regardless if the underlying task is still
running.  This is similar to a race with the timeout, which is handled
already.
(cherry picked from commit a2118a1462)
Co-authored-by: Elvis Pranskevichus <elvis@magic.io>
			
			
This commit is contained in:
		
							parent
							
								
									1036ccb55d
								
							
						
					
					
						commit
						9de6be4e2a
					
				
					 3 changed files with 24 additions and 3 deletions
				
			
		|  | @ -465,9 +465,12 @@ async def wait_for(fut, timeout, *, loop=None): | |||
|         try: | ||||
|             await waiter | ||||
|         except exceptions.CancelledError: | ||||
|             fut.remove_done_callback(cb) | ||||
|             fut.cancel() | ||||
|             raise | ||||
|             if fut.done(): | ||||
|                 return fut.result() | ||||
|             else: | ||||
|                 fut.remove_done_callback(cb) | ||||
|                 fut.cancel() | ||||
|                 raise | ||||
| 
 | ||||
|         if fut.done(): | ||||
|             return fut.result() | ||||
|  |  | |||
|  | @ -1120,6 +1120,22 @@ def gen(): | |||
|         res = loop.run_until_complete(task) | ||||
|         self.assertEqual(res, "ok") | ||||
| 
 | ||||
|     def test_wait_for_cancellation_race_condition(self): | ||||
|         def gen(): | ||||
|             yield 0.1 | ||||
|             yield 0.1 | ||||
|             yield 0.1 | ||||
|             yield 0.1 | ||||
| 
 | ||||
|         loop = self.new_test_loop(gen) | ||||
| 
 | ||||
|         fut = self.new_future(loop) | ||||
|         loop.call_later(0.1, fut.set_result, "ok") | ||||
|         task = loop.create_task(asyncio.wait_for(fut, timeout=1)) | ||||
|         loop.call_later(0.1, task.cancel) | ||||
|         res = loop.run_until_complete(task) | ||||
|         self.assertEqual(res, "ok") | ||||
| 
 | ||||
|     def test_wait_for_waits_for_task_cancellation(self): | ||||
|         loop = asyncio.new_event_loop() | ||||
|         self.addCleanup(loop.close) | ||||
|  |  | |||
|  | @ -0,0 +1,2 @@ | |||
| :meth:`asyncio.wait_for` now properly handles races between cancellation of | ||||
| itself and the completion of the wrapped awaitable. | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Miss Islington (bot)
						Miss Islington (bot)