diff options
author | Gregory P. Smith <greg@mad-scientist.com> | 2010-12-14 14:38:00 (GMT) |
---|---|---|
committer | Gregory P. Smith <greg@mad-scientist.com> | 2010-12-14 14:38:00 (GMT) |
commit | e85db2bbb84ba90c03022860f76ca3cdcdf199c6 (patch) | |
tree | db3bd69dee55a3b2b1db47c54ed8a9d7d0a1ebf7 | |
parent | 32ef70c827997f869a8d8393e8bde74016b6c8a9 (diff) | |
download | cpython-e85db2bbb84ba90c03022860f76ca3cdcdf199c6.zip cpython-e85db2bbb84ba90c03022860f76ca3cdcdf199c6.tar.gz cpython-e85db2bbb84ba90c03022860f76ca3cdcdf199c6.tar.bz2 |
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.
-rw-r--r-- | Lib/subprocess.py | 16 | ||||
-rw-r--r-- | Lib/test/subprocessdata/sigchild_ignore.py | 6 | ||||
-rw-r--r-- | Lib/test/test_subprocess.py | 10 | ||||
-rw-r--r-- | Misc/NEWS | 4 |
4 files changed, 34 insertions, 2 deletions
diff --git a/Lib/subprocess.py b/Lib/subprocess.py index ac46ce8..452611c 100644 --- a/Lib/subprocess.py +++ b/Lib/subprocess.py @@ -1295,7 +1295,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 try: exception_name, hex_errno, err_msg = data.split(b':', 2) except ValueError: @@ -1358,7 +1362,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 index 0000000..1d03303 --- /dev/null +++ b/Lib/test/subprocessdata/sigchild_ignore.py @@ -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() diff --git a/Lib/test/test_subprocess.py b/Lib/test/test_subprocess.py index 0804a13..1e97bac 100644 --- a/Lib/test/test_subprocess.py +++ b/Lib/test/test_subprocess.py @@ -1073,6 +1073,16 @@ class POSIXProcessTestCase(BaseTestCase): close_fds=False, pass_fds=(fd, ))) self.assertIn('overriding close_fds', str(context.warning)) + 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) + @unittest.skipUnless(mswindows, "Windows specific tests") class Win32ProcessTestCase(BaseTestCase): @@ -33,6 +33,10 @@ Library added in 3.2beta1) to allow specifying a specific list of file descriptors to keep open in the child process. +- 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. + What's New in Python 3.2 Beta 1? ================================ |