import signal
import builtins
import warnings
+ import errno
# Exception classes used by this module.
-class CalledProcessError(Exception):
+class SubprocessError(Exception): pass
+
+
+class CalledProcessError(SubprocessError):
"""This exception is raised when a process run by check_call() or
check_output() returns a non-zero exit status.
The exit status will be stored in the returncode attribute;
if self.stdin:
if input is not None:
- self.stdin.write(input)
+ try:
+ self.stdin.write(input)
+ except IOError as e:
+ if e.errno != errno.EPIPE:
+ raise
self.stdin.close()
+ # Wait for the reader threads, or time out. If we time out, the
+ # threads remain reading and the fds left open in case the user
+ # calls communicate again.
+ if self.stdout is not None:
+ self.stdout_thread.join(self._remaining_time(endtime))
+ if self.stdout_thread.isAlive():
+ raise TimeoutExpired(self.args, orig_timeout)
+ if self.stderr is not None:
+ self.stderr_thread.join(self._remaining_time(endtime))
+ if self.stderr_thread.isAlive():
+ raise TimeoutExpired(self.args, orig_timeout)
+
+ # Collect the output from and close both pipes, now that we know
+ # both have been read successfully.
+ stdout = None
+ stderr = None
if self.stdout:
- stdout_thread.join()
+ stdout = self._stdout_buff
+ self.stdout.close()
if self.stderr:
- stderr_thread.join()
+ stderr = self._stderr_buff
+ self.stderr.close()
# All data exchanged. Translate lists into strings.
if stdout is not None:
for fd, mode in ready:
if mode & select.POLLOUT:
- chunk = input[input_offset : input_offset + _PIPE_BUF]
+ chunk = self._input[self._input_offset :
+ self._input_offset + _PIPE_BUF]
- self._input_offset += os.write(fd, chunk)
- if self._input_offset >= len(self._input):
- close_unregister_and_remove(fd)
+ try:
- input_offset += os.write(fd, chunk)
++ self._input_offset += os.write(fd, chunk)
+ except OSError as e:
+ if e.errno == errno.EPIPE:
+ close_unregister_and_remove(fd)
+ else:
+ raise
+ else:
- if input_offset >= len(input):
++ if self._input_offset >= len(self._input):
+ close_unregister_and_remove(fd)
elif mode & select_POLLIN_POLLPRI:
data = os.read(fd, 4096)
if not data:
# file objects; they are no longer using C stdio!
if self.stdin in wlist:
- chunk = input[input_offset : input_offset + _PIPE_BUF]
+ chunk = self._input[self._input_offset :
+ self._input_offset + _PIPE_BUF]
- bytes_written = os.write(self.stdin.fileno(), chunk)
- self._input_offset += bytes_written
- if self._input_offset >= len(self._input):
- self.stdin.close()
- self._write_set.remove(self.stdin)
+ try:
+ bytes_written = os.write(self.stdin.fileno(), chunk)
+ except OSError as e:
+ if e.errno == errno.EPIPE:
+ self.stdin.close()
- write_set.remove(self.stdin)
++ self._write_set.remove(self.stdin)
+ else:
+ raise
+ else:
- input_offset += bytes_written
- if input_offset >= len(input):
++ self._input_offset += bytes_written
++ if self._input_offset >= len(self._input):
+ self.stdin.close()
- write_set.remove(self.stdin)
++ self._write_set.remove(self.stdin)
if self.stdout in rlist:
data = os.read(self.stdout.fileno(), 1024)