]> granicus.if.org Git - python/commitdiff
Issue #12493: subprocess: communicate() handles EINTR
authorVictor Stinner <victor.stinner@haypocalc.com>
Tue, 5 Jul 2011 12:00:56 +0000 (14:00 +0200)
committerVictor Stinner <victor.stinner@haypocalc.com>
Tue, 5 Jul 2011 12:00:56 +0000 (14:00 +0200)
subprocess.Popen.communicate() now also handles EINTR errors if the process has
only one pipe.

Lib/subprocess.py
Lib/test/test_subprocess.py
Misc/NEWS

index 06285e9462cb99aee13e1db1fd4cc7e81ca9c71c..0523219b5a68824488b98c4ed8c4d8ee8ed542a3 100644 (file)
@@ -450,7 +450,7 @@ def _eintr_retry_call(func, *args):
     while True:
         try:
             return func(*args)
-        except OSError as e:
+        except (OSError, IOError) as e:
             if e.errno == errno.EINTR:
                 continue
             raise
@@ -804,10 +804,10 @@ class Popen(object):
                             raise
                 self.stdin.close()
             elif self.stdout:
-                stdout = self.stdout.read()
+                stdout = _eintr_retry_call(self.stdout.read)
                 self.stdout.close()
             elif self.stderr:
-                stderr = self.stderr.read()
+                stderr = _eintr_retry_call(self.stderr.read)
                 self.stderr.close()
             self.wait()
             return (stdout, stderr)
index 4a563b98669d492cdb7e8965edb5d47cab7a7f29..78e7a0e15f7648699dabda413b30105da8eb61dc 100644 (file)
@@ -675,6 +675,22 @@ class ProcessTestCase(BaseTestCase):
         time.sleep(2)
         p.communicate(b"x" * 2**20)
 
+    def test_communicate_eintr(self):
+        # Issue #12493: communicate() should handle EINTR
+        def handler(signum, frame):
+            pass
+        old_handler = signal.signal(signal.SIGALRM, handler)
+        self.addCleanup(signal.signal, signal.SIGALRM, old_handler)
+
+        # the process is running for 2 seconds
+        args = [sys.executable, "-c", 'import time; time.sleep(2)']
+        for stream in ('stdout', 'stderr'):
+            kw = {stream: subprocess.PIPE}
+            with subprocess.Popen(args, **kw) as process:
+                signal.alarm(1)
+                # communicate() will be interrupted by SIGALRM
+                process.communicate()
+
 
 # context manager
 class _SuppressCoreFiles(object):
index ba0b55b27f49dc1ddfe1c5d199b26a0e48426cdc..ae0ed58226e23ad889128ced06c4d9010d39d7e7 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -21,6 +21,9 @@ Core and Builtins
 Library
 -------
 
+- Issue #12493: subprocess: Popen.communicate() now also handles EINTR errors
+  if the process has only one pipe.
+
 - Issue #12467: warnings: fix a race condition if a warning is emitted at
   shutdown, if globals()['__file__'] is None.