mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 13:41:24 +00:00 
			
		
		
		
	Issue #1068268: The subprocess module now handles EINTR in internal
os.waitpid and os.read system calls where appropriate.
This commit is contained in:
		
							parent
							
								
									fb501123e3
								
							
						
					
					
						commit
						cce211f88c
					
				
					 3 changed files with 38 additions and 4 deletions
				
			
		|  | @ -476,6 +476,16 @@ def _cleanup(): | |||
| STDOUT = -2 | ||||
| 
 | ||||
| 
 | ||||
| def _eintr_retry_call(func, *args): | ||||
|     while True: | ||||
|         try: | ||||
|             return func(*args) | ||||
|         except OSError, e: | ||||
|             if e.errno == errno.EINTR: | ||||
|                 continue | ||||
|             raise | ||||
| 
 | ||||
| 
 | ||||
| def call(*popenargs, **kwargs): | ||||
|     """Run command with arguments.  Wait for command to complete, then | ||||
|     return the returncode attribute. | ||||
|  | @ -1173,13 +1183,14 @@ def _execute_child(self, args, executable, preexec_fn, close_fds, | |||
|                     os.close(errwrite) | ||||
| 
 | ||||
|                 # Wait for exec to fail or succeed; possibly raising exception | ||||
|                 data = os.read(errpipe_read, 1048576) # Exception limited to 1M | ||||
|                 # Exception limited to 1M | ||||
|                 data = _eintr_retry_call(os.read, errpipe_read, 1048576) | ||||
|             finally: | ||||
|                 # be sure the FD is closed no matter what | ||||
|                 os.close(errpipe_read) | ||||
| 
 | ||||
|             if data != "": | ||||
|                 os.waitpid(self.pid, 0) | ||||
|                 _eintr_retry_call(os.waitpid, self.pid, 0) | ||||
|                 child_exception = pickle.loads(data) | ||||
|                 for fd in (p2cwrite, c2pread, errread): | ||||
|                     if fd is not None: | ||||
|  | @ -1215,7 +1226,7 @@ def wait(self): | |||
|             """Wait for child process to terminate.  Returns returncode | ||||
|             attribute.""" | ||||
|             if self.returncode is None: | ||||
|                 pid, sts = os.waitpid(self.pid, 0) | ||||
|                 pid, sts = _eintr_retry_call(os.waitpid, self.pid, 0) | ||||
|                 self._handle_exitstatus(sts) | ||||
|             return self.returncode | ||||
| 
 | ||||
|  |  | |||
|  | @ -4,6 +4,7 @@ | |||
| import sys | ||||
| import signal | ||||
| import os | ||||
| import errno | ||||
| import tempfile | ||||
| import time | ||||
| import re | ||||
|  | @ -772,11 +773,30 @@ def tearDown(self): | |||
|         ProcessTestCase.tearDown(self) | ||||
| 
 | ||||
| 
 | ||||
| class HelperFunctionTests(unittest.TestCase): | ||||
|     def test_eintr_retry_call(self): | ||||
|         record_calls = [] | ||||
|         def fake_os_func(*args): | ||||
|             record_calls.append(args) | ||||
|             if len(record_calls) == 2: | ||||
|                 raise OSError(errno.EINTR, "fake interrupted system call") | ||||
|             return tuple(reversed(args)) | ||||
| 
 | ||||
|         self.assertEqual((999, 256), | ||||
|                          subprocess._eintr_retry_call(fake_os_func, 256, 999)) | ||||
|         self.assertEqual([(256, 999)], record_calls) | ||||
|         # This time there will be an EINTR so it will loop once. | ||||
|         self.assertEqual((666,), | ||||
|                          subprocess._eintr_retry_call(fake_os_func, 666)) | ||||
|         self.assertEqual([(256, 999), (666,), (666,)], record_calls) | ||||
| 
 | ||||
| 
 | ||||
| def test_main(): | ||||
|     unit_tests = (ProcessTestCase, | ||||
|                   POSIXProcessTestCase, | ||||
|                   Win32ProcessTestCase, | ||||
|                   ProcessTestCaseNoPoll) | ||||
|                   ProcessTestCaseNoPoll, | ||||
|                   HelperFunctionTests) | ||||
| 
 | ||||
|     test_support.run_unittest(*unit_tests) | ||||
|     test_support.reap_children() | ||||
|  |  | |||
|  | @ -75,6 +75,9 @@ Library | |||
| - Issue #7481: When a threading.Thread failed to start it would leave the | ||||
|   instance stuck in initial state and present in threading.enumerate(). | ||||
| 
 | ||||
| - Issue #1068268: The subprocess module now handles EINTR in internal | ||||
|   os.waitpid and os.read system calls where appropriate. | ||||
| 
 | ||||
| Extension Modules | ||||
| ----------------- | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Gregory P. Smith
						Gregory P. Smith