Index: Lib/subprocess.py =================================================================== --- Lib/subprocess.py (revision 70797) +++ Lib/subprocess.py (working copy) @@ -1126,6 +1126,96 @@ def _communicate(self, input): + try: + select.poll + stdout, stderr = self._communicate_with_poll(input) + except AttributeError: + stdout, stderr = self._communicate_with_select(input) + + # All data exchanged. Translate lists into strings. + if stdout is not None: + stdout = ''.join(stdout) + if stderr is not None: + stderr = ''.join(stderr) + + # Translate newlines, if requested. We cannot let the file + # object do the translation: It is based on stdio, which is + # impossible to combine with select (unless forcing no + # buffering). + if self.universal_newlines and hasattr(file, 'newlines'): + if stdout: + stdout = self._translate_newlines(stdout) + if stderr: + stderr = self._translate_newlines(stderr) + + self.wait() + return (stdout, stderr) + + + def _communicate_with_poll(self, input): + stdout = None # Return + stderr = None # Return + fd2file = {} + fd2output = {} + + poller = select.poll() + def register_and_append(file_obj, eventmask): + poller.register(file_obj.fileno(), eventmask) + fd2file[file_obj.fileno()] = file_obj + + def close_unregister_and_remove(fd): + poller.unregister(fd) + fd2file[fd].close() + fd2file.pop(fd) + + if self.stdin: + # Flush stdio buffer. This might block, if the user has + # been writing to .stdin in an uncontrolled fashion. + self.stdin.flush() + if input: + register_and_append(self.stdin, select.POLLOUT) + else: + self.stdin.close() + if self.stdout: + register_and_append(self.stdout, select.POLLIN|select.POLLPRI) + fd2output[self.stdout.fileno()] = stdout = [] + if self.stderr: + register_and_append(self.stderr, select.POLLIN|select.POLLPRI) + fd2output[self.stderr.fileno()] = stderr = [] + + input_offset = 0 + while fd2file: + try: + ready = poller.poll() + except select.error, e: + if e.args[0] == errno.EINTR: + continue + raise + + for fd, mode in ready: + close_fd = False + if mode & select.POLLOUT: + # When select has indicated that the file is writable, + # we can write up to PIPE_BUF bytes without risk + # blocking. POSIX defines PIPE_BUF >= 512 + chunk = input[input_offset : input_offset + 512] + bytes_written = os.write(fd, chunk) + input_offset += bytes_written + if input_offset >= len(input): + close_unregister_and_remove(fd) + elif mode & (select.POLLIN|select.POLLPRI): + data = os.read(fd, 1024) + if data == "": + close_unregister_and_remove(fd) + fd2output[fd].append(data) + else: + # Ignore hang up or errors. + close_unregister_and_remove(fd) + + return (stdout, stderr) + + + def _communicate_with_select(self, input): read_set = [] write_set = [] stdout = None # Return @@ -1149,7 +1239,8 @@ input_offset = 0 while read_set or write_set: try: - rlist, wlist, xlist = select.select(read_set, write_set, []) + rlist, wlist, xlist = select.select( + read_set, write_set, []) except select.error, e: if e.args[0] == errno.EINTR: continue @@ -1180,23 +1271,6 @@ read_set.remove(self.stderr) stderr.append(data) - # All data exchanged. Translate lists into strings. - if stdout is not None: - stdout = ''.join(stdout) - if stderr is not None: - stderr = ''.join(stderr) - - # Translate newlines, if requested. We cannot let the file - # object do the translation: It is based on stdio, which is - # impossible to combine with select (unless forcing no - # buffering). - if self.universal_newlines and hasattr(file, 'newlines'): - if stdout: - stdout = self._translate_newlines(stdout) - if stderr: - stderr = self._translate_newlines(stderr) - - self.wait() return (stdout, stderr) def send_signal(self, sig):