]> granicus.if.org Git - python/commitdiff
Merged revisions 87233 via svnmerge from
authorGregory P. Smith <greg@mad-scientist.com>
Tue, 14 Dec 2010 15:02:53 +0000 (15:02 +0000)
committerGregory P. Smith <greg@mad-scientist.com>
Tue, 14 Dec 2010 15:02:53 +0000 (15:02 +0000)
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.
........

Lib/subprocess.py
Lib/test/subprocessdata/sigchild_ignore.py [new file with mode: 0644]
Lib/test/test_subprocess.py
Misc/NEWS

index 24bf32182759f141a28e0ff4c497e1f1ac5f33cf..4c235d9a6147424ebe34ebe1e831a66ea3d6d708 100644 (file)
@@ -1194,7 +1194,11 @@ class Popen(object):
                 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:
@@ -1240,7 +1244,15 @@ class Popen(object):
             """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
 
diff --git a/Lib/test/subprocessdata/sigchild_ignore.py b/Lib/test/subprocessdata/sigchild_ignore.py
new file mode 100644 (file)
index 0000000..1d03303
--- /dev/null
@@ -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()
index 37c4e0fc77c0678c1956afa3091a17d6615d40ec..26adf225d56c15751105516a278ad70917a0819f 100644 (file)
@@ -778,6 +778,16 @@ class POSIXProcessTestCase(BaseTestCase):
         self.assertStderrEqual(stderr, '')
         self.assertEqual(p.wait(), -signal.SIGTERM)
 
+    def test_wait_when_sigchild_ignored(self):
+        # NOTE: sigchild_ignore.py may not be an effective test on all OSes.
+        sigchild_ignore = test_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)
+
 
 @unittest.skipUnless(mswindows, "Windows specific tests")
 class Win32ProcessTestCase(BaseTestCase):
index 2d12879e6f0ae181c9961a5b210d95084f904b82..b49539b735982adde0871be2d656f9fb6a67d35f 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -34,6 +34,10 @@ Library
 
 - 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.
+
 Extension Modules
 -----------------