From 28562f19e8dd806458050397b9a406b2779733ab Mon Sep 17 00:00:00 2001 From: adam j hartz Date: Thu, 12 May 2016 21:48:33 -0400 Subject: [PATCH] prevent deadlock from filling buffer --- xonsh/built_ins.py | 41 +++++++++++++++++++++++++++++++---------- 1 file changed, 31 insertions(+), 10 deletions(-) diff --git a/xonsh/built_ins.py b/xonsh/built_ins.py index ca426edf7..30480fe6e 100644 --- a/xonsh/built_ins.py +++ b/xonsh/built_ins.py @@ -421,13 +421,17 @@ def run_subproc(cmds, captured=False): elif prev_proc is not None: stdin = prev_proc.stdout # set standard output + _stdout_name = None + _stderr_name = None if 'stdout' in streams: if ix != last_cmd: raise XonshError('Multiple redirects for stdout') stdout = streams['stdout'][-1] procinfo['stdout_redirect'] = streams['stdout'][:-1] elif _capture_streams or ix != last_cmd: - stdout = PIPE + _stdout = tempfile.NamedTemporaryFile(delete=False) + _stdout_name = _stdout.name + stdout = open(_stdout_name, 'w') elif builtins.__xonsh_stdout_uncaptured__ is not None: stdout = builtins.__xonsh_stdout_uncaptured__ else: @@ -437,7 +441,9 @@ def run_subproc(cmds, captured=False): stderr = streams['stderr'][-1] procinfo['stderr_redirect'] = streams['stderr'][:-1] elif captured == 'object': - stderr = PIPE + _stderr = tempfile.NamedTemporaryFile(delete=False) + _stderr_name = _stderr.name + stderr = open(_stderr_name, 'w') elif builtins.__xonsh_stderr_uncaptured__ is not None: stderr = builtins.__xonsh_stderr_uncaptured__ uninew = (ix == last_cmd) and (not _capture_streams) @@ -552,7 +558,13 @@ def run_subproc(cmds, captured=False): # get output output = b'' if write_target is None: - if prev_proc.stdout not in (None, sys.stdout): + if _stdout_name is not None: + stdout = open(_stdout_name, 'rb') + stdout.seek(0) + output = stdout.read() + stdout.close() + os.unlink(_stdout_name) + elif prev_proc.stdout not in (None, sys.stdout): output = prev_proc.stdout.read() if _capture_streams: # to get proper encoding from Popen, we have to @@ -562,13 +574,22 @@ def run_subproc(cmds, captured=False): output = output.replace('\r\n', '\n') else: hist.last_cmd_out = output - if (captured == 'object' and - prev_proc.stderr not in {None, sys.stderr}): - errout = prev_proc.stderr.read() - errout = errout.decode(encoding=ENV.get('XONSH_ENCODING'), - errors=ENV.get('XONSH_ENCODING_ERRORS')) - errout = errout.replace('\r\n', '\n') - procinfo['stderr'] = errout + if captured == 'object': # get stderr as well + named = _stderr_name is not None + unnamed = prev_proc.stderr not in {None, sys.stderr} + if named: + stderr = open(_stderr_name, 'rb') + stderr.seek(0) + errout = stderr.read() + stderr.close() + os.unlink(_stderr_name) + elif unnamed: + errout = prev_proc.stderr.read() + if named or unnamed: + errout = errout.decode(encoding=ENV.get('XONSH_ENCODING'), + errors=ENV.get('XONSH_ENCODING_ERRORS')) + errout = errout.replace('\r\n', '\n') + procinfo['stderr'] = errout if (not prev_is_proxy and hist.last_cmd_rtn is not None and