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