1 diff --git a/third_party/android_testrunner/run_command.py b/third_party/android_testrunner/run_command.py 2 index d398daa..6b84156 100644 3 --- a/third_party/android_testrunner/run_command.py 4 +++ b/third_party/android_testrunner/run_command.py 5 @@ -19,6 +19,7 @@ 6 import os 7 import signal 8 import subprocess 9 +import tempfile 10 import threading 11 import time 12 13 @@ -80,31 +81,36 @@ def RunOnce(cmd, timeout_time=None, return_output=True, stdin_input=None): 14 """ 15 start_time = time.time() 16 so = [] 17 - pid = [] 18 global _abort_on_error, error_occurred 19 error_occurred = False 20 21 + if return_output: 22 + output_dest = tempfile.TemporaryFile(bufsize=0) 23 + else: 24 + # None means direct to stdout 25 + output_dest = None 26 + if stdin_input: 27 + stdin_dest = subprocess.PIPE 28 + else: 29 + stdin_dest = None 30 + pipe = subprocess.Popen( 31 + cmd, 32 + executable='/bin/bash', 33 + stdin=stdin_dest, 34 + stdout=output_dest, 35 + stderr=subprocess.STDOUT, 36 + shell=True, close_fds=True, 37 + preexec_fn=lambda: signal.signal(signal.SIGPIPE, signal.SIG_DFL)) 38 + 39 def Run(): 40 global error_occurred 41 - if return_output: 42 - output_dest = subprocess.PIPE 43 - else: 44 - # None means direct to stdout 45 - output_dest = None 46 - if stdin_input: 47 - stdin_dest = subprocess.PIPE 48 - else: 49 - stdin_dest = None 50 - pipe = subprocess.Popen( 51 - cmd, 52 - executable='/bin/bash', 53 - stdin=stdin_dest, 54 - stdout=output_dest, 55 - stderr=subprocess.STDOUT, 56 - shell=True) 57 - pid.append(pipe.pid) 58 try: 59 - output = pipe.communicate(input=stdin_input)[0] 60 + pipe.communicate(input=stdin_input) 61 + output = None 62 + if return_output: 63 + output_dest.seek(0) 64 + output = output_dest.read() 65 + output_dest.close() 66 if output is not None and len(output) > 0: 67 so.append(output) 68 except OSError, e: 69 @@ -119,27 +125,17 @@ def RunOnce(cmd, timeout_time=None, return_output=True, stdin_input=None): 70 71 t = threading.Thread(target=Run) 72 t.start() 73 - 74 - break_loop = False 75 - while not break_loop: 76 - if not t.isAlive(): 77 - break_loop = True 78 - 79 - # Check the timeout 80 - if (not break_loop and timeout_time is not None 81 - and time.time() > start_time + timeout_time): 82 - try: 83 - os.kill(pid[0], signal.SIGKILL) 84 - except OSError: 85 - # process already dead. No action required. 86 - pass 87 - 88 + t.join(timeout_time) 89 + if t.isAlive(): 90 + try: 91 + pipe.kill() 92 + except OSError: 93 + # Can't kill a dead process. 94 + pass 95 + finally: 96 logger.SilentLog("about to raise a timeout for: %s" % cmd) 97 raise errors.WaitForResponseTimedOutError 98 - if not break_loop: 99 - time.sleep(0.1) 100 101 - t.join() 102 output = "".join(so) 103 if _abort_on_error and error_occurred: 104 raise errors.AbortError(msg=output) 105