This repository was archived by the owner on Apr 29, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathpython-2.6.6-fix-subprocess-Popen-communicate-broken-by-SIGCHLD.patch
82 lines (74 loc) · 3.6 KB
/
python-2.6.6-fix-subprocess-Popen-communicate-broken-by-SIGCHLD.patch
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# The below patch was modified to apply to RHEL 6 Python 2.6
# HG changeset patch
# User Gregory P. Smith <[email protected]>
# Date 1292338973 0
# Node ID 072ee3f743c21f3770ccf13ad48e10a18048063f
# Parent 8ccf58b0a5da776006d7fc98d9e6975c82265a78
Merged revisions 87233 via svnmerge from
svn+ssh://[email protected]/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.
........
diff --git a/Lib/subprocess.py b/Lib/subprocess.py
--- a/Lib/subprocess.py
+++ b/Lib/subprocess.py
@@ -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):
delay = min(delay * 2, remaining, .05)
time.sleep(delay)
elif 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
--- /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
--- a/Lib/test/test_subprocess.py
+++ b/Lib/test/test_subprocess.py
@@ -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):