mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 05:31:20 +00:00 
			
		
		
		
	Issue #17018: Make Process.join() retry if os.waitpid() fails with EINTR.
This commit is contained in:
		
							parent
							
								
									8fd366978d
								
							
						
					
					
						commit
						7aaa1ef858
					
				
					 3 changed files with 46 additions and 6 deletions
				
			
		|  | @ -35,6 +35,7 @@ | |||
| import os | ||||
| import sys | ||||
| import signal | ||||
| import errno | ||||
| 
 | ||||
| from multiprocessing import util, process | ||||
| 
 | ||||
|  | @ -128,12 +129,17 @@ def __init__(self, process_obj): | |||
| 
 | ||||
|         def poll(self, flag=os.WNOHANG): | ||||
|             if self.returncode is None: | ||||
|                 try: | ||||
|                     pid, sts = os.waitpid(self.pid, flag) | ||||
|                 except os.error: | ||||
|                     # Child process not yet created. See #1731717 | ||||
|                     # e.errno == errno.ECHILD == 10 | ||||
|                     return None | ||||
|                 while True: | ||||
|                     try: | ||||
|                         pid, sts = os.waitpid(self.pid, flag) | ||||
|                     except os.error as e: | ||||
|                         if e.errno == errno.EINTR: | ||||
|                             continue | ||||
|                         # Child process not yet created. See #1731717 | ||||
|                         # e.errno == errno.ECHILD == 10 | ||||
|                         return None | ||||
|                     else: | ||||
|                         break | ||||
|                 if pid == self.pid: | ||||
|                     if os.WIFSIGNALED(sts): | ||||
|                         self.returncode = -os.WTERMSIG(sts) | ||||
|  |  | |||
|  | @ -2167,6 +2167,38 @@ def test_level(self): | |||
| #         logger.warn('foo') | ||||
| #         assert self.__handled | ||||
| 
 | ||||
| # | ||||
| # Check that Process.join() retries if os.waitpid() fails with EINTR | ||||
| # | ||||
| 
 | ||||
| class _TestPollEintr(BaseTestCase): | ||||
| 
 | ||||
|     ALLOWED_TYPES = ('processes',) | ||||
| 
 | ||||
|     @classmethod | ||||
|     def _killer(cls, pid): | ||||
|         time.sleep(0.5) | ||||
|         os.kill(pid, signal.SIGUSR1) | ||||
| 
 | ||||
|     @unittest.skipUnless(hasattr(signal, 'SIGUSR1'), 'requires SIGUSR1') | ||||
|     def test_poll_eintr(self): | ||||
|         got_signal = [False] | ||||
|         def record(*args): | ||||
|             got_signal[0] = True | ||||
|         pid = os.getpid() | ||||
|         oldhandler = signal.signal(signal.SIGUSR1, record) | ||||
|         try: | ||||
|             killer = self.Process(target=self._killer, args=(pid,)) | ||||
|             killer.start() | ||||
|             p = self.Process(target=time.sleep, args=(1,)) | ||||
|             p.start() | ||||
|             p.join() | ||||
|             self.assertTrue(got_signal[0]) | ||||
|             self.assertEqual(p.exitcode, 0) | ||||
|             killer.join() | ||||
|         finally: | ||||
|             signal.signal(signal.SIGUSR1, oldhandler) | ||||
| 
 | ||||
| # | ||||
| # Test to verify handle verification, see issue 3321 | ||||
| # | ||||
|  |  | |||
|  | @ -230,6 +230,8 @@ Core and Builtins | |||
| Library | ||||
| ------- | ||||
| 
 | ||||
| - Issue #17018: Make Process.join() retry if os.waitpid() fails with EINTR. | ||||
| 
 | ||||
| - Issue #14720: sqlite3: Convert datetime microseconds correctly. | ||||
|   Patch by Lowe Thiderman. | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Richard Oudkerk
						Richard Oudkerk