[Python-checkins] [3.8] bpo-35182: fix communicate() crash after child closes its pipes (GH-18117) (GH-18148)
Miss Islington (bot)
webhook-mailer at python.org
Thu Jan 23 18:31:41 EST 2020
https://github.com/python/cpython/commit/5654f83b9706af88040f515791f1cdc5d81cd9d6
commit: 5654f83b9706af88040f515791f1cdc5d81cd9d6
branch: 3.8
author: Alex Rebert <alex at forallsecure.com>
committer: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com>
date: 2020-01-23T15:31:29-08:00
summary:
[3.8] bpo-35182: fix communicate() crash after child closes its pipes (GH-18117) (GH-18148)
When communicate() is called in a loop, it crashes when the child process
has already closed any piped standard stream, but still continues to be running
Co-authored-by: Andriy Maletsky <andriy.maletsky at gmail.com>.
(cherry picked from commit d3ae95e1e945ed20297e1c38ba43a18b7a868ab6)
Co-authored-by: Alex Rebert <alex at forallsecure.com>
https://bugs.python.org/issue35182
files:
A Misc/NEWS.d/next/Library/2019-10-31-19-23-25.bpo-35182.hzeNl9.rst
M Lib/subprocess.py
M Lib/test/test_subprocess.py
diff --git a/Lib/subprocess.py b/Lib/subprocess.py
index 85b9ea0785466..5c2c2f05093f7 100644
--- a/Lib/subprocess.py
+++ b/Lib/subprocess.py
@@ -1848,9 +1848,9 @@ def _communicate(self, input, endtime, orig_timeout):
with _PopenSelector() as selector:
if self.stdin and input:
selector.register(self.stdin, selectors.EVENT_WRITE)
- if self.stdout:
+ if self.stdout and not self.stdout.closed:
selector.register(self.stdout, selectors.EVENT_READ)
- if self.stderr:
+ if self.stderr and not self.stderr.closed:
selector.register(self.stderr, selectors.EVENT_READ)
while selector.get_map():
diff --git a/Lib/test/test_subprocess.py b/Lib/test/test_subprocess.py
index b2afd127dfed8..80acb06e4f920 100644
--- a/Lib/test/test_subprocess.py
+++ b/Lib/test/test_subprocess.py
@@ -2910,6 +2910,17 @@ def test_stopped(self):
self.assertEqual(returncode, -3)
+ def test_communicate_repeated_call_after_stdout_close(self):
+ proc = subprocess.Popen([sys.executable, '-c',
+ 'import os, time; os.close(1), time.sleep(2)'],
+ stdout=subprocess.PIPE)
+ while True:
+ try:
+ proc.communicate(timeout=0.1)
+ return
+ except subprocess.TimeoutExpired:
+ pass
+
@unittest.skipUnless(mswindows, "Windows specific tests")
class Win32ProcessTestCase(BaseTestCase):
diff --git a/Misc/NEWS.d/next/Library/2019-10-31-19-23-25.bpo-35182.hzeNl9.rst b/Misc/NEWS.d/next/Library/2019-10-31-19-23-25.bpo-35182.hzeNl9.rst
new file mode 100644
index 0000000000000..9438cd8f9fd0b
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2019-10-31-19-23-25.bpo-35182.hzeNl9.rst
@@ -0,0 +1,3 @@
+Fixed :func:`Popen.communicate` subsequent call crash when the child process
+has already closed any piped standard stream, but still continues to be
+running. Patch by Andriy Maletsky.
More information about the Python-checkins
mailing list