1# Copyright 2016 the V8 project authors. All rights reserved. 2# Use of this source code is governed by a BSD-style license that can be 3# found in the LICENSE file. 4 5# Fork from commands.py and output.py in v8 test driver. 6 7import signal 8import subprocess 9import sys 10from threading import Event, Timer 11 12 13class Output(object): 14 def __init__(self, exit_code, timed_out, stdout, pid): 15 self.exit_code = exit_code 16 self.timed_out = timed_out 17 self.stdout = stdout 18 self.pid = pid 19 20 def HasCrashed(self): 21 # Timed out tests will have exit_code -signal.SIGTERM. 22 if self.timed_out: 23 return False 24 return (self.exit_code < 0 and 25 self.exit_code != -signal.SIGABRT) 26 27 def HasTimedOut(self): 28 return self.timed_out 29 30 31def Execute(args, cwd, timeout=None): 32 popen_args = [c for c in args if c != ""] 33 try: 34 process = subprocess.Popen( 35 args=popen_args, 36 stdout=subprocess.PIPE, 37 stderr=subprocess.STDOUT, 38 cwd=cwd 39 ) 40 except Exception as e: 41 sys.stderr.write("Error executing: %s\n" % popen_args) 42 raise e 43 44 timeout_event = Event() 45 46 def kill_process(): 47 timeout_event.set() 48 try: 49 process.kill() 50 except OSError: 51 sys.stderr.write('Error: Process %s already ended.\n' % process.pid) 52 53 54 timer = Timer(timeout, kill_process) 55 timer.start() 56 stdout, _ = process.communicate() 57 timer.cancel() 58 59 return Output( 60 process.returncode, 61 timeout_event.is_set(), 62 stdout.decode('utf-8', 'replace').encode('utf-8'), 63 process.pid, 64 ) 65