Skip to content

Commit 312efbc

Browse files
committed
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. ........
1 parent dacb804 commit 312efbc

4 files changed

Lines changed: 34 additions & 2 deletions

File tree

Lib/subprocess.py

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1194,7 +1194,11 @@ def _execute_child(self, args, executable, preexec_fn, close_fds,
11941194
os.close(errpipe_read)
11951195

11961196
if data != "":
1197-
_eintr_retry_call(os.waitpid, self.pid, 0)
1197+
try:
1198+
_eintr_retry_call(os.waitpid, self.pid, 0)
1199+
except OSError as e:
1200+
if e.errno != errno.ECHILD:
1201+
raise
11981202
child_exception = pickle.loads(data)
11991203
for fd in (p2cwrite, c2pread, errread):
12001204
if fd is not None:
@@ -1240,7 +1244,15 @@ def wait(self):
12401244
"""Wait for child process to terminate. Returns returncode
12411245
attribute."""
12421246
if self.returncode is None:
1243-
pid, sts = _eintr_retry_call(os.waitpid, self.pid, 0)
1247+
try:
1248+
pid, sts = _eintr_retry_call(os.waitpid, self.pid, 0)
1249+
except OSError as e:
1250+
if e.errno != errno.ECHILD:
1251+
raise
1252+
# This happens if SIGCLD is set to be ignored or waiting
1253+
# for child processes has otherwise been disabled for our
1254+
# process. This child is dead, we can't get the status.
1255+
sts = 0
12441256
self._handle_exitstatus(sts)
12451257
return self.returncode
12461258

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import signal, subprocess, sys
2+
# On Linux this causes os.waitpid to fail with OSError as the OS has already
3+
# reaped our child process. The wait() passing the OSError on to the caller
4+
# and causing us to exit with an error is what we are testing against.
5+
signal.signal(signal.SIGCLD, signal.SIG_IGN)
6+
subprocess.Popen([sys.executable, '-c', 'print("albatross")']).wait()

Lib/test/test_subprocess.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -778,6 +778,16 @@ def test_terminate(self):
778778
self.assertStderrEqual(stderr, '')
779779
self.assertEqual(p.wait(), -signal.SIGTERM)
780780

781+
def test_wait_when_sigchild_ignored(self):
782+
# NOTE: sigchild_ignore.py may not be an effective test on all OSes.
783+
sigchild_ignore = test_support.findfile("sigchild_ignore.py",
784+
subdir="subprocessdata")
785+
p = subprocess.Popen([sys.executable, sigchild_ignore],
786+
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
787+
stdout, stderr = p.communicate()
788+
self.assertEqual(0, p.returncode, "sigchild_ignore.py exited"
789+
" non-zero with this error:\n%s" % stderr)
790+
781791

782792
@unittest.skipUnless(mswindows, "Windows specific tests")
783793
class Win32ProcessTestCase(BaseTestCase):

Misc/NEWS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@ Library
3434

3535
- Issue #10464: netrc now correctly handles lines with embedded '#' characters.
3636

37+
- Issue #1731717: Fixed the problem where subprocess.wait() could cause an
38+
OSError exception when The OS had been told to ignore SIGCLD in our process
39+
or otherwise not wait for exiting child processes.
40+
3741
Extension Modules
3842
-----------------
3943

0 commit comments

Comments
 (0)