diff -r 760f222103c7 Doc/library/subprocess.rst --- a/Doc/library/subprocess.rst Mon Mar 02 09:36:48 2015 -0500 +++ b/Doc/library/subprocess.rst Tue Mar 03 10:45:00 2015 +0100 @@ -533,9 +533,17 @@ functions. with Popen(["ifconfig"], stdout=PIPE) as proc: log.write(proc.stdout.read()) + The context manager ignores broken pipe errors when closing the process's + stdin: call explicitly ``proc.stdin.flush()`` and ``proc.stdin.close()`` to + get broken pipe errors. + .. versionchanged:: 3.2 Added context manager support. + .. versionchanged:: 3.5 + The context manager support now ignores broken pipe errors as + the :meth:`~Popen.communicate` method. + Exceptions ^^^^^^^^^^ @@ -642,6 +650,11 @@ Instances of the :class:`Popen` class ha ``None`` in the result tuple, you need to give ``stdout=PIPE`` and/or ``stderr=PIPE`` too. + Broken pipe errors are ignored when sending data to the process's stdin. If + the process exits before reading all input data or closes its stdin, the + parent gets a broken pipe error. The method ignore this error and so may not + send all *input* data. + If the process does not terminate after *timeout* seconds, a :exc:`TimeoutExpired` exception will be raised. Catching this exception and retrying communication will not lose any output. diff -r 760f222103c7 Lib/subprocess.py --- a/Lib/subprocess.py Mon Mar 02 09:36:48 2015 -0500 +++ b/Lib/subprocess.py Tue Mar 03 10:45:00 2015 +0100 @@ -892,12 +892,12 @@ class Popen(object): self.stdout.close() if self.stderr: self.stderr.close() - try: # Flushing a BufferedWriter may raise an error - if self.stdin: - self.stdin.close() - finally: - # Wait for the process to terminate, to avoid zombies. - self.wait() + if self.stdin: + # Ignore broken pipe error when closing stdin. stdin is buffered: + # close() can flush buffered data and so write data. + self._stdin_write(None) + # Wait for the process to terminate, to avoid zombies. + self.wait() def __del__(self, _maxsize=sys.maxsize): if not self._child_created: @@ -915,20 +915,22 @@ class Popen(object): return self._devnull def _stdin_write(self, input): - if input: - try: + try: + if input: self.stdin.write(input) - except BrokenPipeError: - # communicate() must ignore broken pipe error + # stdin is buffered: close() can flush buffered data and so write + # data. We also want to catch errors on close() + self.stdin.close() + except BrokenPipeError: + # communicate() must ignore broken pipe error + pass + except OSError as e: + if e.errno == errno.EINVAL and self.poll() is not None: + # Issue #19612: On Windows, stdin.write() fails with EINVAL + # if the process already exited before the write pass - except OSError as e: - if e.errno == errno.EINVAL and self.poll() is not None: - # Issue #19612: On Windows, stdin.write() fails with EINVAL - # if the process already exited before the write - pass - else: - raise - self.stdin.close() + else: + raise def communicate(self, input=None, timeout=None): """Interact with process: Send data to stdin. Read data from