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 subprocess
30b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochimport sys
31014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochfrom threading import Timer
32b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
33b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochfrom ..local import utils
34b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochfrom ..objects import output
35b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
36b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
37b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochSEM_INVALID_VALUE = -1
38b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochSEM_NOGPFAULTERRORBOX = 0x0002  # Microsoft Platform SDK WinBase.h
39b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
40b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
41b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochdef Win32SetErrorMode(mode):
42b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  prev_error_mode = SEM_INVALID_VALUE
43b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  try:
44b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    import ctypes
45b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    prev_error_mode = \
46b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        ctypes.windll.kernel32.SetErrorMode(mode)  #@UndefinedVariable
47b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  except ImportError:
48b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    pass
49b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return prev_error_mode
50b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
51b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
52b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochdef RunProcess(verbose, timeout, args, **rest):
53b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if verbose: print "#", " ".join(args)
54b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  popen_args = args
55b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  prev_error_mode = SEM_INVALID_VALUE
56b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if utils.IsWindows():
57b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    popen_args = subprocess.list2cmdline(args)
58b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    # Try to change the error mode to avoid dialogs on fatal errors. Don't
59b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    # touch any existing error mode flags by merging the existing error mode.
60b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    # See http://blogs.msdn.com/oldnewthing/archive/2004/07/27/198410.aspx.
61b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    error_mode = SEM_NOGPFAULTERRORBOX
62b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    prev_error_mode = Win32SetErrorMode(error_mode)
63b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Win32SetErrorMode(error_mode | prev_error_mode)
64014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
65014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  try:
66014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    process = subprocess.Popen(
67014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      args=popen_args,
68014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      stdout=subprocess.PIPE,
69014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      stderr=subprocess.PIPE,
70014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      **rest
71014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    )
72014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  except Exception as e:
73014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    sys.stderr.write("Error executing: %s\n" % popen_args)
74014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    raise e
75014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
76b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (utils.IsWindows() and prev_error_mode != SEM_INVALID_VALUE):
77b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Win32SetErrorMode(prev_error_mode)
78014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
79014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  def kill_process(process, timeout_result):
80014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    timeout_result[0] = True
81b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    try:
82014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if utils.IsWindows():
83014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if verbose:
84014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          print "Attempting to kill process %d" % process.pid
85014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          sys.stdout.flush()
86014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        tk = subprocess.Popen(
87014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            'taskkill /T /F /PID %d' % process.pid,
88014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            stdout=subprocess.PIPE,
89014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            stderr=subprocess.PIPE,
90014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        )
91014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        stdout, stderr = tk.communicate()
92014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if verbose:
93014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          print "Taskkill results for %d" % process.pid
94014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          print stdout
95014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          print stderr
96014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          print "Return code: %d" % tk.returncode
97014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          sys.stdout.flush()
98014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      else:
99014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        process.kill()
100014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    except OSError:
101014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      sys.stderr.write('Error: Process %s already ended.\n' % process.pid)
102014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
103014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  # Pseudo object to communicate with timer thread.
104014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  timeout_result = [False]
105014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
106014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  timer = Timer(timeout, kill_process, [process, timeout_result])
107014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  timer.start()
108014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  stdout, stderr = process.communicate()
109014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  timer.cancel()
1103b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
1113b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  return output.Output(
1123b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      process.returncode,
1133b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      timeout_result[0],
114f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      stdout.decode('utf-8', 'replace').encode('utf-8'),
115f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      stderr.decode('utf-8', 'replace').encode('utf-8'),
1163b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      process.pid,
1173b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  )
118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochdef Execute(args, verbose=False, timeout=None):
121014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  args = [ c for c in args if c != "" ]
1223b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  return RunProcess(verbose, timeout, args=args)
123