mirror of
				https://github.com/python/cpython.git
				synced 2025-11-03 23:21:29 +00:00 
			
		
		
		
	bpo-40550: Fix time-of-check/time-of-action issue in subprocess.Popen.send_signal. (GH-20010)
send_signal() now swallows the exception if the process it thought was still alive winds up not to exist anymore (always a plausible race condition despite the checks). Co-authored-by: Gregory P. Smith <greg@krypto.org>
This commit is contained in:
		
							parent
							
								
									31729366e2
								
							
						
					
					
						commit
						01a202ab6b
					
				
					 3 changed files with 19 additions and 1 deletions
				
			
		| 
						 | 
					@ -2078,7 +2078,11 @@ def send_signal(self, sig):
 | 
				
			||||||
            # The race condition can still happen if the race condition
 | 
					            # The race condition can still happen if the race condition
 | 
				
			||||||
            # described above happens between the returncode test
 | 
					            # described above happens between the returncode test
 | 
				
			||||||
            # and the kill() call.
 | 
					            # and the kill() call.
 | 
				
			||||||
            os.kill(self.pid, sig)
 | 
					            try:
 | 
				
			||||||
 | 
					                os.kill(self.pid, sig)
 | 
				
			||||||
 | 
					            except ProcessLookupError:
 | 
				
			||||||
 | 
					                # Supress the race condition error; bpo-40550.
 | 
				
			||||||
 | 
					                pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        def terminate(self):
 | 
					        def terminate(self):
 | 
				
			||||||
            """Terminate the process with SIGTERM
 | 
					            """Terminate the process with SIGTERM
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3229,6 +3229,19 @@ def test_send_signal_race(self):
 | 
				
			||||||
        # so Popen failed to read it and uses a default returncode instead.
 | 
					        # so Popen failed to read it and uses a default returncode instead.
 | 
				
			||||||
        self.assertIsNotNone(proc.returncode)
 | 
					        self.assertIsNotNone(proc.returncode)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_send_signal_race2(self):
 | 
				
			||||||
 | 
					        # bpo-40550: the process might exist between the returncode check and
 | 
				
			||||||
 | 
					        # the kill operation
 | 
				
			||||||
 | 
					        p = subprocess.Popen([sys.executable, '-c', 'exit(1)'])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # wait for process to exit
 | 
				
			||||||
 | 
					        while not p.returncode:
 | 
				
			||||||
 | 
					            p.poll()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        with mock.patch.object(p, 'poll', new=lambda: None):
 | 
				
			||||||
 | 
					            p.returncode = None
 | 
				
			||||||
 | 
					            p.send_signal(signal.SIGTERM)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_communicate_repeated_call_after_stdout_close(self):
 | 
					    def test_communicate_repeated_call_after_stdout_close(self):
 | 
				
			||||||
        proc = subprocess.Popen([sys.executable, '-c',
 | 
					        proc = subprocess.Popen([sys.executable, '-c',
 | 
				
			||||||
                                 'import os, time; os.close(1), time.sleep(2)'],
 | 
					                                 'import os, time; os.close(1), time.sleep(2)'],
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1 @@
 | 
				
			||||||
 | 
					Fix time-of-check/time-of-action issue in subprocess.Popen.send_signal.
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue