Commit 0b81f67b authored by machenbach's avatar machenbach Committed by Commit bot

[test-runner] Improve test execution without tmp files for output.

BUG=chromium:485932
LOG=n

Review URL: https://codereview.chromium.org/1134703002

Cr-Commit-Position: refs/heads/master@{#28334}
parent 0208b8e3
......@@ -27,27 +27,13 @@
import os
import signal
import subprocess
import sys
import tempfile
import time
from threading import Timer
from ..local import utils
from ..objects import output
def KillProcessWithID(pid):
if utils.IsWindows():
os.popen('taskkill /T /F /PID %d' % pid)
else:
os.kill(pid, signal.SIGTERM)
MAX_SLEEP_TIME = 0.1
INITIAL_SLEEP_TIME = 0.0001
SLEEP_TIME_FACTOR = 1.25
SEM_INVALID_VALUE = -1
SEM_NOGPFAULTERRORBOX = 0x0002 # Microsoft Platform SDK WinBase.h
......@@ -76,76 +62,36 @@ def RunProcess(verbose, timeout, args, **rest):
prev_error_mode = Win32SetErrorMode(error_mode)
Win32SetErrorMode(error_mode | prev_error_mode)
process = subprocess.Popen(
shell=utils.IsWindows(),
args=popen_args,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
**rest
)
if (utils.IsWindows() and prev_error_mode != SEM_INVALID_VALUE):
Win32SetErrorMode(prev_error_mode)
# Compute the end time - if the process crosses this limit we
# consider it timed out.
if timeout is None: end_time = None
else: end_time = time.time() + timeout
timed_out = False
# Repeatedly check the exit code from the process in a
# loop and keep track of whether or not it times out.
exit_code = None
sleep_time = INITIAL_SLEEP_TIME
while exit_code is None:
if (not end_time is None) and (time.time() >= end_time):
# Kill the process and wait for it to exit.
KillProcessWithID(process.pid)
exit_code = process.wait()
timed_out = True
else:
exit_code = process.poll()
time.sleep(sleep_time)
sleep_time = sleep_time * SLEEP_TIME_FACTOR
if sleep_time > MAX_SLEEP_TIME:
sleep_time = MAX_SLEEP_TIME
return (exit_code, timed_out)
def PrintError(string):
sys.stderr.write(string)
sys.stderr.write("\n")
def kill_process(process, timeout_result):
timeout_result[0] = True
try:
process.kill()
except OSError:
sys.stderr.write('Error: Process %s already ended.\n' % process.pid)
# Pseudo object to communicate with timer thread.
timeout_result = [False]
def CheckedUnlink(name):
# On Windows, when run with -jN in parallel processes,
# OS often fails to unlink the temp file. Not sure why.
# Need to retry.
# Idea from https://bugs.webkit.org/attachment.cgi?id=75982&action=prettypatch
retry_count = 0
while retry_count < 30:
try:
os.unlink(name)
return
except OSError, e:
retry_count += 1
time.sleep(retry_count * 0.1)
PrintError("os.unlink() " + str(e))
timer = Timer(timeout, kill_process, [process, timeout_result])
timer.start()
stdout, stderr = process.communicate()
timer.cancel()
return process.returncode, timeout_result[0], stdout, stderr
def Execute(args, verbose=False, timeout=None):
try:
args = [ c for c in args if c != "" ]
(fd_out, outname) = tempfile.mkstemp()
(fd_err, errname) = tempfile.mkstemp()
(exit_code, timed_out) = RunProcess(
verbose,
timeout,
args=args,
stdout=fd_out,
stderr=fd_err
)
finally:
# TODO(machenbach): A keyboard interrupt before the assignment to
# fd_out|err can lead to reference errors here.
os.close(fd_out)
os.close(fd_err)
out = file(outname).read()
errors = file(errname).read()
CheckedUnlink(outname)
CheckedUnlink(errname)
return output.Output(exit_code, timed_out, out, errors)
args = [ c for c in args if c != "" ]
exit_code, timed_out, stdout, stderr = RunProcess(
verbose,
timeout,
args=args,
)
return output.Output(exit_code, timed_out, stdout, stderr)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment