summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Lib/subprocess.py4
-rw-r--r--Lib/test/test_subprocess.py11
-rw-r--r--Misc/NEWS.d/next/Library/2019-10-31-19-23-25.bpo-35182.hzeNl9.rst3
3 files changed, 16 insertions, 2 deletions
diff --git a/Lib/subprocess.py b/Lib/subprocess.py
index 79dffd3..26a1e69 100644
--- a/Lib/subprocess.py
+++ b/Lib/subprocess.py
@@ -1983,9 +1983,9 @@ class Popen(object):
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 f1fb934..2bbdbae 100644
--- a/Lib/test/test_subprocess.py
+++ b/Lib/test/test_subprocess.py
@@ -3145,6 +3145,17 @@ class POSIXProcessTestCase(BaseTestCase):
# so Popen failed to read it and uses a default returncode instead.
self.assertIsNotNone(proc.returncode)
+ 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 0000000..9438cd8
--- /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.