[Python-checkins] r87235 - in python/branches/release31-maint: Lib/subprocess.py Lib/test/subprocessdata Lib/test/subprocessdata/sigchild_ignore.py Lib/test/test_subprocess.py Misc/NEWS

gregory.p.smith python-checkins at python.org
Tue Dec 14 16:16:25 CET 2010


Author: gregory.p.smith
Date: Tue Dec 14 16:16:24 2010
New Revision: 87235

Log:
Merged revisions 87233 via svnmerge from 
svn+ssh://pythondev@svn.python.org/python/branches/py3k

........
  r87233 | gregory.p.smith | 2010-12-14 06:38:00 -0800 (Tue, 14 Dec 2010) | 4 lines
  
  Issue #1731717: Fixed the problem where subprocess.wait() could cause an
  OSError exception when The OS had been told to ignore SIGCLD in our process
  or otherwise not wait for exiting child processes.
........


Added:
   python/branches/release31-maint/Lib/test/subprocessdata/
   python/branches/release31-maint/Lib/test/subprocessdata/sigchild_ignore.py
Modified:
   python/branches/release31-maint/   (props changed)
   python/branches/release31-maint/Lib/subprocess.py
   python/branches/release31-maint/Lib/test/test_subprocess.py
   python/branches/release31-maint/Misc/NEWS

Modified: python/branches/release31-maint/Lib/subprocess.py
==============================================================================
--- python/branches/release31-maint/Lib/subprocess.py	(original)
+++ python/branches/release31-maint/Lib/subprocess.py	Tue Dec 14 16:16:24 2010
@@ -1149,7 +1149,11 @@
                 os.close(errpipe_read)
 
             if data:
-                _eintr_retry_call(os.waitpid, self.pid, 0)
+                try:
+                    _eintr_retry_call(os.waitpid, self.pid, 0)
+                except OSError as e:
+                    if e.errno != errno.ECHILD:
+                        raise
                 child_exception = pickle.loads(data)
                 for fd in (p2cwrite, c2pread, errread):
                     if fd is not None:
@@ -1195,7 +1199,15 @@
             """Wait for child process to terminate.  Returns returncode
             attribute."""
             if self.returncode is None:
-                pid, sts = _eintr_retry_call(os.waitpid, self.pid, 0)
+                try:
+                    pid, sts = _eintr_retry_call(os.waitpid, self.pid, 0)
+                except OSError as e:
+                    if e.errno != errno.ECHILD:
+                        raise
+                    # This happens if SIGCLD is set to be ignored or waiting
+                    # for child processes has otherwise been disabled for our
+                    # process.  This child is dead, we can't get the status.
+                    sts = 0
                 self._handle_exitstatus(sts)
             return self.returncode
 

Added: python/branches/release31-maint/Lib/test/subprocessdata/sigchild_ignore.py
==============================================================================
--- (empty file)
+++ python/branches/release31-maint/Lib/test/subprocessdata/sigchild_ignore.py	Tue Dec 14 16:16:24 2010
@@ -0,0 +1,6 @@
+import signal, subprocess, sys
+# On Linux this causes os.waitpid to fail with OSError as the OS has already
+# reaped our child process.  The wait() passing the OSError on to the caller
+# and causing us to exit with an error is what we are testing against.
+signal.signal(signal.SIGCLD, signal.SIG_IGN)
+subprocess.Popen([sys.executable, '-c', 'print("albatross")']).wait()

Modified: python/branches/release31-maint/Lib/test/test_subprocess.py
==============================================================================
--- python/branches/release31-maint/Lib/test/test_subprocess.py	(original)
+++ python/branches/release31-maint/Lib/test/test_subprocess.py	Tue Dec 14 16:16:24 2010
@@ -793,6 +793,17 @@
                 stdout = stdout.rstrip(b'\n\r')
                 self.assertEqual(stdout, value_repr)
 
+        def test_wait_when_sigchild_ignored(self):
+            # NOTE: sigchild_ignore.py may not be an effective test on all OSes.
+            sigchild_ignore = support.findfile("sigchild_ignore.py",
+                                               subdir="subprocessdata")
+            p = subprocess.Popen([sys.executable, sigchild_ignore],
+                                 stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+            stdout, stderr = p.communicate()
+            self.assertEqual(0, p.returncode, "sigchild_ignore.py exited"
+                             " non-zero with this error:\n%s" % stderr)
+
+
     #
     # Windows tests
     #

Modified: python/branches/release31-maint/Misc/NEWS
==============================================================================
--- python/branches/release31-maint/Misc/NEWS	(original)
+++ python/branches/release31-maint/Misc/NEWS	Tue Dec 14 16:16:24 2010
@@ -35,6 +35,10 @@
 
 - Issue #10464: netrc now correctly handles lines with embedded '#' characters.
 
+- Issue #1731717: Fixed the problem where subprocess.wait() could cause an
+  OSError exception when The OS had been told to ignore SIGCLD in our process
+  or otherwise not wait for exiting child processes.
+
 Extensions
 ----------
 


More information about the Python-checkins mailing list