diff -r 12502327d2c0 Lib/subprocess.py --- a/Lib/subprocess.py Tue Feb 16 13:27:45 2016 +1100 +++ b/Lib/subprocess.py Wed Feb 17 12:12:07 2016 +0100 @@ -1021,7 +1021,7 @@ class Popen(object): try: self.stdin.write(input) except BrokenPipeError: - # communicate() must ignore broken pipe error + # communicate() must ignore broken pipe error on stdin pass except OSError as e: if e.errno == errno.EINVAL and self.poll() is not None: @@ -1030,7 +1030,12 @@ class Popen(object): pass else: raise - self.stdin.close() + + try: + self.stdin.close() + except BrokenPipeError: + # communicate() must ignore broken pipe error on stdin + pass def communicate(self, input=None, timeout=None): """Interact with process: Send data to stdin. Read data from @@ -1666,11 +1671,15 @@ class Popen(object): def _communicate(self, input, endtime, orig_timeout): if self.stdin and not self._communication_started: - # Flush stdio buffer. This might block, if the user has - # been writing to .stdin in an uncontrolled fashion. - self.stdin.flush() - if not input: - self.stdin.close() + try: + # Flush stdio buffer. This might block, if the user has + # been writing to .stdin in an uncontrolled fashion. + self.stdin.flush() + if not input: + self.stdin.close() + except BrokenPipeError: + # communicate() must ignore broken pipe error on stdin + pass stdout = None stderr = None diff -r 12502327d2c0 Lib/test/test_subprocess.py --- a/Lib/test/test_subprocess.py Tue Feb 16 13:27:45 2016 +1100 +++ b/Lib/test/test_subprocess.py Wed Feb 17 12:12:07 2016 +0100 @@ -1,4 +1,5 @@ import unittest +from unittest import mock from test.support import script_helper from test import support import subprocess @@ -2664,6 +2665,30 @@ class ContextManagerTests(BaseTestCase): self.assertEqual(proc.returncode, 0) self.assertTrue(proc.stdin.closed) + def test_broken_pipe_stdin_close(self): + # Issue #26372: BrokenPipeError must be ignored on stdin.close() + # in communicate() + proc = subprocess.Popen([sys.executable, '-c', 'pass'], + stdin=subprocess.PIPE) + with proc, mock.patch.object(proc, 'stdin') as m_stdin: + m_stdin.close.side_effect = BrokenPipeError + + # check that BrokenPipeError exception raised by stdin.close() + # in _stdin_write() is ignored + proc.communicate() + + def test_broken_pipe_stdin_close_timeout(self): + # Issue #26372: BrokenPipeError must be ignored on stdin.close() + # in communicate() + proc = subprocess.Popen([sys.executable, '-c', 'pass'], + stdin=subprocess.PIPE) + with proc, mock.patch.object(proc, 'stdin') as m_stdin: + m_stdin.close.side_effect = BrokenPipeError + + # check that BrokenPipeError exception raised by stdin.close() + # in _communicate() is ignored + proc.communicate(timeout=1.0) + def test_main(): unit_tests = (ProcessTestCase,