mirror of
				https://github.com/python/cpython.git
				synced 2025-11-03 23:21:29 +00:00 
			
		
		
		
	Issue #23140, asyncio: Fix cancellation of Process.wait(). Check the state of
the waiter future before setting its result.
This commit is contained in:
		
							parent
							
								
									8c1a4a2326
								
							
						
					
					
						commit
						c447ba04e7
					
				
					 2 changed files with 30 additions and 1 deletions
				
			
		| 
						 | 
					@ -96,6 +96,7 @@ def process_exited(self):
 | 
				
			||||||
        returncode = self._transport.get_returncode()
 | 
					        returncode = self._transport.get_returncode()
 | 
				
			||||||
        while self._waiters:
 | 
					        while self._waiters:
 | 
				
			||||||
            waiter = self._waiters.popleft()
 | 
					            waiter = self._waiters.popleft()
 | 
				
			||||||
 | 
					            if not waiter.cancelled():
 | 
				
			||||||
                waiter.set_result(returncode)
 | 
					                waiter.set_result(returncode)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -223,6 +223,34 @@ def len_message(message):
 | 
				
			||||||
        self.assertEqual(output.rstrip(), b'3')
 | 
					        self.assertEqual(output.rstrip(), b'3')
 | 
				
			||||||
        self.assertEqual(exitcode, 0)
 | 
					        self.assertEqual(exitcode, 0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_cancel_process_wait(self):
 | 
				
			||||||
 | 
					        # Issue #23140: cancel Process.wait()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        @asyncio.coroutine
 | 
				
			||||||
 | 
					        def wait_proc(proc, event):
 | 
				
			||||||
 | 
					            event.set()
 | 
				
			||||||
 | 
					            yield from proc.wait()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        @asyncio.coroutine
 | 
				
			||||||
 | 
					        def cancel_wait():
 | 
				
			||||||
 | 
					            proc = yield from asyncio.create_subprocess_exec(
 | 
				
			||||||
 | 
					                                          *PROGRAM_BLOCKED,
 | 
				
			||||||
 | 
					                                          loop=self.loop)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            # Create an internal future waiting on the process exit
 | 
				
			||||||
 | 
					            event = asyncio.Event(loop=self.loop)
 | 
				
			||||||
 | 
					            task = self.loop.create_task(wait_proc(proc, event))
 | 
				
			||||||
 | 
					            yield from event.wait()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            # Cancel the future
 | 
				
			||||||
 | 
					            task.cancel()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            # Kill the process and wait until it is done
 | 
				
			||||||
 | 
					            proc.kill()
 | 
				
			||||||
 | 
					            yield from proc.wait()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.loop.run_until_complete(cancel_wait())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if sys.platform != 'win32':
 | 
					if sys.platform != 'win32':
 | 
				
			||||||
    # Unix
 | 
					    # Unix
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue