Index: utils/lit/lit/util.py =================================================================== --- utils/lit/lit/util.py +++ utils/lit/lit/util.py @@ -6,6 +6,8 @@ import signal import subprocess import sys +import pty +import select def detectCPUs(): """ @@ -143,6 +145,19 @@ # Close extra file handles on UNIX (on Windows this cannot be done while # also redirecting input). kUseCloseFDs = not (platform.system() == 'Windows') + +def _to_string(str_bytes): + if isinstance(str_bytes, str): + return str_bytes + return str_bytes.encode('utf-8') + +def _convert_string(str_bytes): + try: + return _to_string(str_bytes.decode('utf-8')) + except: + return str(str_bytes) + + def executeCommand(command, cwd=None, env=None): p = subprocess.Popen(command, cwd=cwd, stdin=subprocess.PIPE, @@ -151,26 +166,65 @@ env=env, close_fds=kUseCloseFDs) out,err = p.communicate() exitCode = p.wait() - # Detect Ctrl-C in subprocess. if exitCode == -signal.SIGINT: raise KeyboardInterrupt - def to_string(bytes): - if isinstance(bytes, str): - return bytes - return bytes.encode('utf-8') - # Ensure the resulting output is always of string type. + out = _convert_string(out) + err = _convert_string(err) + + return out, err, exitCode + +def _read_and_close_pty(p): + os.close(p[1]) + with os.fdopen(p[0], 'r') as f: + out = '' + try: + out = _convert_string(f.read()) + except IOError: + pass + return out + +def executeCommandPTY(command, cwd=None, env=None): try: - out = to_string(out.decode('utf-8')) - except: - out = str(out) - try: - err = to_string(err.decode('utf-8')) + out_pty = tuple(pty.openpty()) + err_pty = tuple(pty.openpty()) + kwargs = { + 'stdin' :subprocess.PIPE, + 'stdout':out_pty[1], + 'stderr':err_pty[1], + 'cwd':cwd, + 'env':env, + 'close_fds':kUseCloseFDs, + } + p = subprocess.Popen(command, **kwargs) + exitCode = None + out = '' + err = '' + while True: + exitCode = p.poll() + if exitCode is not None: + break + to_read,_,_ = select.select([out_pty[0], err_pty[0]], [], [], 0.0) + for fd in to_read: + data = _convert_string(os.read(fd, 4096)) + if fd == out_pty[0]: + out += data + else: + err += data + # Detect Ctrl-C in subprocess. + if exitCode == -signal.SIGINT: + raise KeyboardInterrupt + out += _read_and_close_pty(out_pty) + err += _read_and_close_pty(err_pty) except: - err = str(err) - + for fd in out_pty + err_pty: + try: + os.close(fd) + except: + pass + raise return out, err, exitCode def usePlatformSdkOnDarwin(config, lit_config):