]> granicus.if.org Git - python/commitdiff
Issue #15592. Fix regression: subprocess.communicate() breaks on no input with univer...
authorAndrew Svetlov <andrew.svetlov@gmail.com>
Tue, 14 Aug 2012 15:40:21 +0000 (18:40 +0300)
committerAndrew Svetlov <andrew.svetlov@gmail.com>
Tue, 14 Aug 2012 15:40:21 +0000 (18:40 +0300)
Patch by Chris Jerdonek.

1  2 
Lib/subprocess.py
Lib/test/test_subprocess.py

index 7885ba37afc49e3e682041949cf4084a8b747dc6,179f41a85f56c82def6489d77e07f0dede23c66c..35f6f965c51dee3ca21d8aefadbdd46662633b62
@@@ -1536,12 -1455,12 +1536,23 @@@ class Popen(object)
              return (stdout, stderr)
  
  
 -        def _communicate_with_poll(self, input):
++        def _save_input(self, input):
++            # This method is called from the _communicate_with_*() methods
++            # so that if we time out while communicating, we can continue
++            # sending input if we retry.
++            if self.stdin and self._input is None:
++                self._input_offset = 0
++                self._input = input
++                if self.universal_newlines and input is not None:
++                    self._input = self._input.encode(self.stdin.encoding)
++
++
 +        def _communicate_with_poll(self, input, endtime, orig_timeout):
              stdout = None # Return
              stderr = None # Return
 -            fd2file = {}
 -            fd2output = {}
 +
 +            if not self._communication_started:
 +                self._fd2file = {}
  
              poller = select.poll()
              def register_and_append(file_obj, eventmask):
              select_POLLIN_POLLPRI = select.POLLIN | select.POLLPRI
              if self.stdout:
                  register_and_append(self.stdout, select_POLLIN_POLLPRI)
 -                fd2output[self.stdout.fileno()] = stdout = []
 +                stdout = self._fd2output[self.stdout.fileno()]
              if self.stderr:
                  register_and_append(self.stderr, select_POLLIN_POLLPRI)
 -                fd2output[self.stderr.fileno()] = stderr = []
 +                stderr = self._fd2output[self.stderr.fileno()]
  
-             # Save the input here so that if we time out while communicating,
-             # we can continue sending input if we retry.
-             if self.stdin and self._input is None:
-                 self._input_offset = 0
-                 self._input = input
-                 if self.universal_newlines:
-                     self._input = self._input.encode(self.stdin.encoding)
 -            input_offset = 0
 -            while fd2file:
++            self._save_input(input)
 +
 +            while self._fd2file:
 +                timeout = self._remaining_time(endtime)
 +                if timeout is not None and timeout < 0:
 +                    raise TimeoutExpired(self.args, orig_timeout)
                  try:
 -                    ready = poller.poll()
 +                    ready = poller.poll(timeout)
                  except select.error as e:
                      if e.args[0] == errno.EINTR:
                          continue
              return (stdout, stderr)
  
  
 -        def _communicate_with_select(self, input):
 -            read_set = []
 -            write_set = []
 +        def _communicate_with_select(self, input, endtime, orig_timeout):
 +            if not self._communication_started:
 +                self._read_set = []
 +                self._write_set = []
 +                if self.stdin and input:
 +                    self._write_set.append(self.stdin)
 +                if self.stdout:
 +                    self._read_set.append(self.stdout)
 +                if self.stderr:
 +                    self._read_set.append(self.stderr)
 +
-             if self.stdin and self._input is None:
-                 self._input_offset = 0
-                 self._input = input
-                 if self.universal_newlines:
-                     self._input = self._input.encode(self.stdin.encoding)
++            self._save_input(input)
 +
              stdout = None # Return
              stderr = None # Return
  
index 552b13ebd964158751151b9a10e4f6077692288a,9e92a962277e5001b2fb24422be1a0249517bc3c..e591d2fd56cbd17bf4800f5978650c4fffa25e69
@@@ -615,8 -528,8 +615,6 @@@ class ProcessTestCase(BaseTestCase)
                               universal_newlines=1)
          self.addCleanup(p.stdout.close)
          self.addCleanup(p.stderr.close)
--        # BUG: can't give a non-empty stdin because it breaks both the
--        # select- and poll-based communicate() implementations.
          (stdout, stderr) = p.communicate()
          self.assertEqual(stdout,
                           "line2\nline4\nline5\nline6\nline7\nline8")