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:
Geoff Brown 2023-09-13 14:31:43 +00:00
parent 66b4b70e4d
commit 6086cf951e

View File

@ -7,13 +7,11 @@ import subprocess
import sys
import time
import traceback
from threading import Event
from threading import Timer
import mozcrash
import psutil
import six
from mozlog import get_proxy_logger
from mozprocess import ProcessHandler
from talos.utils import TalosError
@ -72,27 +70,23 @@ class ProcessContext(object):
class Reader(object):
def __init__(self, event):
def __init__(self):
self.output = []
self.got_end_timestamp = False
self.got_timeout = False
self.timeout_message = ""
self.got_error = False
self.event = event
self.proc = None
def __call__(self, line):
line = six.ensure_str(line)
line = line.strip("\n")
if line.find("__endTimestamp") != -1:
self.got_end_timestamp = True
self.event.set()
elif line == "TART: TIMEOUT":
self.got_timeout = True
self.timeout_message = "TART"
self.event.set()
elif line.startswith("TEST-UNEXPECTED-FAIL | "):
self.got_error = True
self.event.set()
if not (
"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
the browser has been started. The callback must takes
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
Returns a ProcessContext instance, with available output and pid used.
@ -148,34 +142,42 @@ def run_browser(
context = ProcessContext(is_launcher)
first_time = int(time.time()) * 1000
wait_for_quit_timeout = 20
event = Event()
reader = Reader(event)
reader = Reader()
LOG.info("Using env: %s" % pprint.pformat(kwargs["env"]))
kwargs["storeOutput"] = False
kwargs["processOutputLine"] = reader
kwargs["onFinish"] = event.set
proc = ProcessHandler(command, **kwargs)
timed_out = False
def timeout_handler():
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
proc.run()
LOG.process_start(proc.pid, " ".join(command))
try:
context.process = psutil.Process(proc.pid)
if on_started:
on_started(context.process)
# wait until we saw __endTimestamp in the proc output,
# or the browser just terminated - or we have a timeout
if not event.wait(timeout):
LOG.info("Timeout waiting for test completion; killing browser...")
# try to extract the minidump stack if the browser hangs
kill_and_get_minidump(context, minidump_dir)
raise TalosError("timeout")
# read output until the browser terminates or the timeout is hit
for line in proc.stdout:
reader(line)
if timed_out:
LOG.info("Timeout waiting for test completion; killing browser...")
# 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:
for i in six.moves.range(1, wait_for_quit_timeout):
if proc.wait(1) is not None:
break
proc.wait(wait_for_quit_timeout)
if proc.poll() is None:
LOG.info(
"Browser shutdown timed out after {0} seconds, killing"
@ -193,6 +195,7 @@ def run_browser(
finally:
# this also handle KeyboardInterrupt
# ensure early the process is really terminated
proc_timer.cancel()
return_code = None
try:
return_code = context.kill_process()