mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-23 21:01:08 +00:00
Bug 1851717 - Use subprocess instead of mozprocess in talos r=perftest-reviewers,sparky
Differential Revision: https://phabricator.services.mozilla.com/D187566
This commit is contained in:
parent
66b4b70e4d
commit
6086cf951e
@ -7,13 +7,11 @@ import subprocess
|
|||||||
import sys
|
import sys
|
||||||
import time
|
import time
|
||||||
import traceback
|
import traceback
|
||||||
from threading import Event
|
from threading import Timer
|
||||||
|
|
||||||
import mozcrash
|
import mozcrash
|
||||||
import psutil
|
import psutil
|
||||||
import six
|
|
||||||
from mozlog import get_proxy_logger
|
from mozlog import get_proxy_logger
|
||||||
from mozprocess import ProcessHandler
|
|
||||||
|
|
||||||
from talos.utils import TalosError
|
from talos.utils import TalosError
|
||||||
|
|
||||||
@ -72,27 +70,23 @@ class ProcessContext(object):
|
|||||||
|
|
||||||
|
|
||||||
class Reader(object):
|
class Reader(object):
|
||||||
def __init__(self, event):
|
def __init__(self):
|
||||||
self.output = []
|
self.output = []
|
||||||
self.got_end_timestamp = False
|
self.got_end_timestamp = False
|
||||||
self.got_timeout = False
|
self.got_timeout = False
|
||||||
self.timeout_message = ""
|
self.timeout_message = ""
|
||||||
self.got_error = False
|
self.got_error = False
|
||||||
self.event = event
|
|
||||||
self.proc = None
|
self.proc = None
|
||||||
|
|
||||||
def __call__(self, line):
|
def __call__(self, line):
|
||||||
line = six.ensure_str(line)
|
line = line.strip("\n")
|
||||||
if line.find("__endTimestamp") != -1:
|
if line.find("__endTimestamp") != -1:
|
||||||
self.got_end_timestamp = True
|
self.got_end_timestamp = True
|
||||||
self.event.set()
|
|
||||||
elif line == "TART: TIMEOUT":
|
elif line == "TART: TIMEOUT":
|
||||||
self.got_timeout = True
|
self.got_timeout = True
|
||||||
self.timeout_message = "TART"
|
self.timeout_message = "TART"
|
||||||
self.event.set()
|
|
||||||
elif line.startswith("TEST-UNEXPECTED-FAIL | "):
|
elif line.startswith("TEST-UNEXPECTED-FAIL | "):
|
||||||
self.got_error = True
|
self.got_error = True
|
||||||
self.event.set()
|
|
||||||
|
|
||||||
if not (
|
if not (
|
||||||
"JavaScript error:" in line
|
"JavaScript error:" in line
|
||||||
@ -132,7 +126,7 @@ def run_browser(
|
|||||||
:param on_started: a callback that can be used to do things just after
|
:param on_started: a callback that can be used to do things just after
|
||||||
the browser has been started. The callback must takes
|
the browser has been started. The callback must takes
|
||||||
an argument, which is the psutil.Process instance
|
an argument, which is the psutil.Process instance
|
||||||
:param kwargs: additional keyword arguments for the :class:`ProcessHandler`
|
:param kwargs: additional keyword arguments for the :class:`subprocess.Popen`
|
||||||
instance
|
instance
|
||||||
|
|
||||||
Returns a ProcessContext instance, with available output and pid used.
|
Returns a ProcessContext instance, with available output and pid used.
|
||||||
@ -148,34 +142,42 @@ def run_browser(
|
|||||||
context = ProcessContext(is_launcher)
|
context = ProcessContext(is_launcher)
|
||||||
first_time = int(time.time()) * 1000
|
first_time = int(time.time()) * 1000
|
||||||
wait_for_quit_timeout = 20
|
wait_for_quit_timeout = 20
|
||||||
event = Event()
|
reader = Reader()
|
||||||
reader = Reader(event)
|
|
||||||
|
|
||||||
LOG.info("Using env: %s" % pprint.pformat(kwargs["env"]))
|
LOG.info("Using env: %s" % pprint.pformat(kwargs["env"]))
|
||||||
|
|
||||||
kwargs["storeOutput"] = False
|
timed_out = False
|
||||||
kwargs["processOutputLine"] = reader
|
|
||||||
kwargs["onFinish"] = event.set
|
def timeout_handler():
|
||||||
proc = ProcessHandler(command, **kwargs)
|
nonlocal timed_out
|
||||||
|
timed_out = True
|
||||||
|
|
||||||
|
proc_timer = Timer(timeout, timeout_handler)
|
||||||
|
proc_timer.start()
|
||||||
|
|
||||||
|
proc = subprocess.Popen(
|
||||||
|
command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True, **kwargs
|
||||||
|
)
|
||||||
reader.proc = proc
|
reader.proc = proc
|
||||||
proc.run()
|
|
||||||
|
|
||||||
LOG.process_start(proc.pid, " ".join(command))
|
LOG.process_start(proc.pid, " ".join(command))
|
||||||
try:
|
try:
|
||||||
context.process = psutil.Process(proc.pid)
|
context.process = psutil.Process(proc.pid)
|
||||||
if on_started:
|
if on_started:
|
||||||
on_started(context.process)
|
on_started(context.process)
|
||||||
# wait until we saw __endTimestamp in the proc output,
|
|
||||||
# or the browser just terminated - or we have a timeout
|
# read output until the browser terminates or the timeout is hit
|
||||||
if not event.wait(timeout):
|
for line in proc.stdout:
|
||||||
LOG.info("Timeout waiting for test completion; killing browser...")
|
reader(line)
|
||||||
# try to extract the minidump stack if the browser hangs
|
if timed_out:
|
||||||
kill_and_get_minidump(context, minidump_dir)
|
LOG.info("Timeout waiting for test completion; killing browser...")
|
||||||
raise TalosError("timeout")
|
# try to extract the minidump stack if the browser hangs
|
||||||
|
kill_and_get_minidump(context, minidump_dir)
|
||||||
|
raise TalosError("timeout")
|
||||||
|
break
|
||||||
|
|
||||||
if reader.got_end_timestamp:
|
if reader.got_end_timestamp:
|
||||||
for i in six.moves.range(1, wait_for_quit_timeout):
|
proc.wait(wait_for_quit_timeout)
|
||||||
if proc.wait(1) is not None:
|
|
||||||
break
|
|
||||||
if proc.poll() is None:
|
if proc.poll() is None:
|
||||||
LOG.info(
|
LOG.info(
|
||||||
"Browser shutdown timed out after {0} seconds, killing"
|
"Browser shutdown timed out after {0} seconds, killing"
|
||||||
@ -193,6 +195,7 @@ def run_browser(
|
|||||||
finally:
|
finally:
|
||||||
# this also handle KeyboardInterrupt
|
# this also handle KeyboardInterrupt
|
||||||
# ensure early the process is really terminated
|
# ensure early the process is really terminated
|
||||||
|
proc_timer.cancel()
|
||||||
return_code = None
|
return_code = None
|
||||||
try:
|
try:
|
||||||
return_code = context.kill_process()
|
return_code = context.kill_process()
|
||||||
|
Loading…
Reference in New Issue
Block a user