| Index: subprocess2.py
|
| diff --git a/subprocess2.py b/subprocess2.py
|
| index 3ad804791fcabb0b423be212f31ef16c5d060064..ef95d6f8701c4c7634782e8729e89fab1c07dd44 100644
|
| --- a/subprocess2.py
|
| +++ b/subprocess2.py
|
| @@ -173,25 +173,22 @@ class Popen(subprocess.Popen):
|
|
|
| self.stdout_cb = None
|
| self.stderr_cb = None
|
| - self.stdout_void = False
|
| - self.stderr_void = False
|
| - def fix(stream):
|
| + self.stdin_is_void = False
|
| + self.stdout_is_void = False
|
| + self.stderr_is_void = False
|
| +
|
| + if kwargs.get('stdin') is VOID:
|
| + kwargs['stdin'] = open(os.devnull, 'r')
|
| + self.stdin_is_void = True
|
| +
|
| + for stream in ('stdout', 'stderr'):
|
| if kwargs.get(stream) in (VOID, os.devnull):
|
| - # Replaces VOID with handle to /dev/null.
|
| - # Create a temporary file to workaround python's deadlock.
|
| - # http://docs.python.org/library/subprocess.html#subprocess.Popen.wait
|
| - # When the pipe fills up, it will deadlock this process. Using a real
|
| - # file works around that issue.
|
| kwargs[stream] = open(os.devnull, 'w')
|
| - setattr(self, stream + '_void', True)
|
| + setattr(self, stream + '_is_void', True)
|
| if callable(kwargs.get(stream)):
|
| - # Callable stdout/stderr should be used only with call() wrappers.
|
| setattr(self, stream + '_cb', kwargs[stream])
|
| kwargs[stream] = PIPE
|
|
|
| - fix('stdout')
|
| - fix('stderr')
|
| -
|
| self.start = time.time()
|
| self.timeout = None
|
| self.shell = kwargs.get('shell', None)
|
| @@ -288,6 +285,9 @@ class Popen(subprocess.Popen):
|
| target=_queue_pipe_read, args=(self.stderr, 'stderr'))
|
| if input:
|
| threads['stdin'] = threading.Thread(target=write_stdin)
|
| + elif self.stdin:
|
| + # Pipe but no input, make sure it's closed.
|
| + self.stdin.close()
|
| for t in threads.itervalues():
|
| t.start()
|
|
|
| @@ -346,20 +346,19 @@ class Popen(subprocess.Popen):
|
| stderr = None
|
| # Convert to a lambda to workaround python's deadlock.
|
| # http://docs.python.org/library/subprocess.html#subprocess.Popen.wait
|
| - # When the pipe fills up, it will deadlock this process. Using a thread
|
| - # works around that issue. No need for thread safe function since the call
|
| - # backs are guaranteed to be called from the main thread.
|
| - if self.stdout and not self.stdout_cb and not self.stdout_void:
|
| - stdout = cStringIO.StringIO()
|
| - self.stdout_cb = stdout.write
|
| - if self.stderr and not self.stderr_cb and not self.stderr_void:
|
| - stderr = cStringIO.StringIO()
|
| - self.stderr_cb = stderr.write
|
| + # When the pipe fills up, it would deadlock this process.
|
| + if self.stdout and not self.stdout_cb and not self.stdout_is_void:
|
| + stdout = []
|
| + self.stdout_cb = stdout.append
|
| + if self.stderr and not self.stderr_cb and not self.stderr_is_void:
|
| + stderr = []
|
| + self.stderr_cb = stderr.append
|
| self._tee_threads(input)
|
| - if stdout:
|
| - stdout = stdout.getvalue()
|
| - if stderr:
|
| - stderr = stderr.getvalue()
|
| + if stdout is not None:
|
| + stdout = ''.join(stdout)
|
| + stderr = None
|
| + if stderr is not None:
|
| + stderr = ''.join(stderr)
|
| return (stdout, stderr)
|
|
|
|
|
| @@ -374,17 +373,16 @@ def communicate(args, timeout=None, **kwargs):
|
| """
|
| stdin = kwargs.pop('stdin', None)
|
| if stdin is not None:
|
| - if stdin is VOID:
|
| - kwargs['stdin'] = open(os.devnull, 'r')
|
| - stdin = None
|
| - else:
|
| - assert isinstance(stdin, basestring)
|
| + if isinstance(stdin, basestring):
|
| # When stdin is passed as an argument, use it as the actual input data and
|
| # set the Popen() parameter accordingly.
|
| kwargs['stdin'] = PIPE
|
| + else:
|
| + kwargs['stdin'] = stdin
|
| + stdin = None
|
|
|
| proc = Popen(args, **kwargs)
|
| - if stdin not in (None, VOID):
|
| + if stdin:
|
| return proc.communicate(stdin, timeout), proc.returncode
|
| else:
|
| return proc.communicate(None, timeout), proc.returncode
|
|
|