Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(270)

Side by Side Diff: tools/testrunner/local/commands.py

Issue 1134703002: [test-runner] Improve test execution without tmp files for output. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: nit Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 # Copyright 2012 the V8 project authors. All rights reserved. 1 # Copyright 2012 the V8 project authors. All rights reserved.
2 # Redistribution and use in source and binary forms, with or without 2 # Redistribution and use in source and binary forms, with or without
3 # modification, are permitted provided that the following conditions are 3 # modification, are permitted provided that the following conditions are
4 # met: 4 # met:
5 # 5 #
6 # * Redistributions of source code must retain the above copyright 6 # * Redistributions of source code must retain the above copyright
7 # notice, this list of conditions and the following disclaimer. 7 # notice, this list of conditions and the following disclaimer.
8 # * Redistributions in binary form must reproduce the above 8 # * Redistributions in binary form must reproduce the above
9 # copyright notice, this list of conditions and the following 9 # copyright notice, this list of conditions and the following
10 # disclaimer in the documentation and/or other materials provided 10 # disclaimer in the documentation and/or other materials provided
11 # with the distribution. 11 # with the distribution.
12 # * Neither the name of Google Inc. nor the names of its 12 # * Neither the name of Google Inc. nor the names of its
13 # contributors may be used to endorse or promote products derived 13 # contributors may be used to endorse or promote products derived
14 # from this software without specific prior written permission. 14 # from this software without specific prior written permission.
15 # 15 #
16 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 18 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 19 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 21 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 27
28 28
29 import os 29 import os
30 import signal
31 import subprocess 30 import subprocess
32 import sys 31 from threading import Timer
33 import tempfile
34 import time
35 32
36 from ..local import utils 33 from ..local import utils
37 from ..objects import output 34 from ..objects import output
38 35
39 36
40 def KillProcessWithID(pid):
41 if utils.IsWindows():
42 os.popen('taskkill /T /F /PID %d' % pid)
43 else:
44 os.kill(pid, signal.SIGTERM)
45
46
47 MAX_SLEEP_TIME = 0.1
48 INITIAL_SLEEP_TIME = 0.0001
49 SLEEP_TIME_FACTOR = 1.25
50
51 SEM_INVALID_VALUE = -1 37 SEM_INVALID_VALUE = -1
52 SEM_NOGPFAULTERRORBOX = 0x0002 # Microsoft Platform SDK WinBase.h 38 SEM_NOGPFAULTERRORBOX = 0x0002 # Microsoft Platform SDK WinBase.h
53 39
54 40
55 def Win32SetErrorMode(mode): 41 def Win32SetErrorMode(mode):
56 prev_error_mode = SEM_INVALID_VALUE 42 prev_error_mode = SEM_INVALID_VALUE
57 try: 43 try:
58 import ctypes 44 import ctypes
59 prev_error_mode = \ 45 prev_error_mode = \
60 ctypes.windll.kernel32.SetErrorMode(mode) #@UndefinedVariable 46 ctypes.windll.kernel32.SetErrorMode(mode) #@UndefinedVariable
61 except ImportError: 47 except ImportError:
62 pass 48 pass
63 return prev_error_mode 49 return prev_error_mode
64 50
65 51
66 def RunProcess(verbose, timeout, args, **rest): 52 def RunProcess(verbose, timeout, args, **rest):
67 if verbose: print "#", " ".join(args) 53 if verbose: print "#", " ".join(args)
68 popen_args = args 54 popen_args = args
69 prev_error_mode = SEM_INVALID_VALUE 55 prev_error_mode = SEM_INVALID_VALUE
70 if utils.IsWindows(): 56 if utils.IsWindows():
71 popen_args = subprocess.list2cmdline(args) 57 popen_args = subprocess.list2cmdline(args)
72 # Try to change the error mode to avoid dialogs on fatal errors. Don't 58 # 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. 59 # 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. 60 # See http://blogs.msdn.com/oldnewthing/archive/2004/07/27/198410.aspx.
75 error_mode = SEM_NOGPFAULTERRORBOX 61 error_mode = SEM_NOGPFAULTERRORBOX
76 prev_error_mode = Win32SetErrorMode(error_mode) 62 prev_error_mode = Win32SetErrorMode(error_mode)
77 Win32SetErrorMode(error_mode | prev_error_mode) 63 Win32SetErrorMode(error_mode | prev_error_mode)
78 process = subprocess.Popen( 64 process = subprocess.Popen(
79 shell=utils.IsWindows(),
80 args=popen_args, 65 args=popen_args,
66 stdout=subprocess.PIPE,
67 stderr=subprocess.PIPE,
81 **rest 68 **rest
82 ) 69 )
83 if (utils.IsWindows() and prev_error_mode != SEM_INVALID_VALUE): 70 if (utils.IsWindows() and prev_error_mode != SEM_INVALID_VALUE):
84 Win32SetErrorMode(prev_error_mode) 71 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 72
73 def kill_process(process, timeout_result):
74 timeout_result[0] = True
75 try:
76 process.kill()
77 except OSError:
78 sys.stderr.write('Error: Process %s already ended.\n' % process.pid)
108 79
109 def PrintError(string): 80 # Pseudo object to communicate with timer thread.
110 sys.stderr.write(string) 81 timeout_result = [False]
111 sys.stderr.write("\n")
112 82
113 83 timer = Timer(timeout, kill_process, [process, timeout_result])
114 def CheckedUnlink(name): 84 timer.start()
115 # On Windows, when run with -jN in parallel processes, 85 stdout, stderr = process.communicate()
116 # OS often fails to unlink the temp file. Not sure why. 86 timer.cancel()
117 # Need to retry. 87 return process.returncode, timeout_result[0], stdout, stderr
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 88
129 89
130 def Execute(args, verbose=False, timeout=None): 90 def Execute(args, verbose=False, timeout=None):
131 try: 91 args = [ c for c in args if c != "" ]
132 args = [ c for c in args if c != "" ] 92 exit_code, timed_out, stdout, stderr = RunProcess(
133 (fd_out, outname) = tempfile.mkstemp() 93 verbose,
134 (fd_err, errname) = tempfile.mkstemp() 94 timeout,
135 (exit_code, timed_out) = RunProcess( 95 args=args,
136 verbose, 96 )
137 timeout, 97 return output.Output(exit_code, timed_out, stdout, stderr)
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)
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698