1bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant# Copyright 2012 the V8 project authors. All rights reserved. 2bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant# Redistribution and use in source and binary forms, with or without 3f5256e16dfc425c1d466f6308d4026d529ce9e0bHoward Hinnant# modification, are permitted provided that the following conditions are 4bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant# met: 5b64f8b07c104c6cc986570ac8ee0ed16a9f23976Howard Hinnant# 6b64f8b07c104c6cc986570ac8ee0ed16a9f23976Howard Hinnant# * Redistributions of source code must retain the above copyright 7bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant# notice, this list of conditions and the following disclaimer. 8bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant# * Redistributions in binary form must reproduce the above 9bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant# copyright notice, this list of conditions and the following 10bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant# disclaimer in the documentation and/or other materials provided 11bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant# with the distribution. 12bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant# * Neither the name of Google Inc. nor the names of its 13bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant# contributors may be used to endorse or promote products derived 14bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant# from this software without specific prior written permission. 15bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant# 16bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1906d8bf6ce2008526732ae40ad46f7ff031c409e7Howard Hinnant# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2306d8bf6ce2008526732ae40ad46f7ff031c409e7Howard Hinnant# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2506d8bf6ce2008526732ae40ad46f7ff031c409e7Howard Hinnant# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 2613aaf422e49fa4b66642966bfc6078b5d9adde12Sean Hunt# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant 28bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant 29bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnantimport os 30bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnantimport signal 31bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnantimport subprocess 32bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnantimport sys 3306d8bf6ce2008526732ae40ad46f7ff031c409e7Howard Hinnantimport tempfile 34bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnantimport time 3506d8bf6ce2008526732ae40ad46f7ff031c409e7Howard Hinnant 3613aaf422e49fa4b66642966bfc6078b5d9adde12Sean Huntfrom ..local import utils 37bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnantfrom ..objects import output 38bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant 39bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant 40bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnantdef KillProcessWithID(pid): 41bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant if utils.IsWindows(): 42bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant os.popen('taskkill /T /F /PID %d' % pid) 4306d8bf6ce2008526732ae40ad46f7ff031c409e7Howard Hinnant else: 44bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant os.kill(pid, signal.SIGTERM) 45 46 47MAX_SLEEP_TIME = 0.1 48INITIAL_SLEEP_TIME = 0.0001 49SLEEP_TIME_FACTOR = 1.25 50 51SEM_INVALID_VALUE = -1 52SEM_NOGPFAULTERRORBOX = 0x0002 # Microsoft Platform SDK WinBase.h 53 54 55def Win32SetErrorMode(mode): 56 prev_error_mode = SEM_INVALID_VALUE 57 try: 58 import ctypes 59 prev_error_mode = \ 60 ctypes.windll.kernel32.SetErrorMode(mode) #@UndefinedVariable 61 except ImportError: 62 pass 63 return prev_error_mode 64 65 66def RunProcess(verbose, timeout, args, **rest): 67 if verbose: print "#", " ".join(args) 68 popen_args = args 69 prev_error_mode = SEM_INVALID_VALUE 70 if utils.IsWindows(): 71 popen_args = subprocess.list2cmdline(args) 72 # Try to change the error mode to avoid dialogs on fatal errors. Don't 73 # touch any existing error mode flags by merging the existing error mode. 74 # See http://blogs.msdn.com/oldnewthing/archive/2004/07/27/198410.aspx. 75 error_mode = SEM_NOGPFAULTERRORBOX 76 prev_error_mode = Win32SetErrorMode(error_mode) 77 Win32SetErrorMode(error_mode | prev_error_mode) 78 process = subprocess.Popen( 79 shell=utils.IsWindows(), 80 args=popen_args, 81 **rest 82 ) 83 if (utils.IsWindows() and prev_error_mode != SEM_INVALID_VALUE): 84 Win32SetErrorMode(prev_error_mode) 85 # Compute the end time - if the process crosses this limit we 86 # consider it timed out. 87 if timeout is None: end_time = None 88 else: end_time = time.time() + timeout 89 timed_out = False 90 # Repeatedly check the exit code from the process in a 91 # loop and keep track of whether or not it times out. 92 exit_code = None 93 sleep_time = INITIAL_SLEEP_TIME 94 while exit_code is None: 95 if (not end_time is None) and (time.time() >= end_time): 96 # Kill the process and wait for it to exit. 97 KillProcessWithID(process.pid) 98 exit_code = process.wait() 99 timed_out = True 100 else: 101 exit_code = process.poll() 102 time.sleep(sleep_time) 103 sleep_time = sleep_time * SLEEP_TIME_FACTOR 104 if sleep_time > MAX_SLEEP_TIME: 105 sleep_time = MAX_SLEEP_TIME 106 return (exit_code, timed_out) 107 108 109def PrintError(string): 110 sys.stderr.write(string) 111 sys.stderr.write("\n") 112 113 114def CheckedUnlink(name): 115 # On Windows, when run with -jN in parallel processes, 116 # OS often fails to unlink the temp file. Not sure why. 117 # Need to retry. 118 # Idea from https://bugs.webkit.org/attachment.cgi?id=75982&action=prettypatch 119 retry_count = 0 120 while retry_count < 30: 121 try: 122 os.unlink(name) 123 return 124 except OSError, e: 125 retry_count += 1 126 time.sleep(retry_count * 0.1) 127 PrintError("os.unlink() " + str(e)) 128 129 130def Execute(args, verbose=False, timeout=None): 131 try: 132 args = [ c for c in args if c != "" ] 133 (fd_out, outname) = tempfile.mkstemp() 134 (fd_err, errname) = tempfile.mkstemp() 135 (exit_code, timed_out) = RunProcess( 136 verbose, 137 timeout, 138 args=args, 139 stdout=fd_out, 140 stderr=fd_err 141 ) 142 finally: 143 # TODO(machenbach): A keyboard interrupt before the assignment to 144 # fd_out|err can lead to reference errors here. 145 os.close(fd_out) 146 os.close(fd_err) 147 out = file(outname).read() 148 errors = file(errname).read() 149 CheckedUnlink(outname) 150 CheckedUnlink(errname) 151 return output.Output(exit_code, timed_out, out, errors) 152