[Dexter] Add timeout options
Adds a pair of options for Dexter that allow the user to specify a timeout duration. These options are: * --timeout-total: Times out if the total run-time of the debugger session exceeds <timeout-total> seconds. * --timeout-breakpoint: Times out if the time without hitting a breakpoint exceeds <timeout-breakpoint> seconds. Reviewed By: Orlando Differential Revision: https://reviews.llvm.org/D145063
This commit is contained in:
@@ -16,6 +16,7 @@ from dex.debugger.DebuggerControllers.ControllerHelpers import in_source_file, u
|
||||
from dex.debugger.DebuggerControllers.DebuggerControllerBase import DebuggerControllerBase
|
||||
from dex.debugger.DebuggerBase import DebuggerBase
|
||||
from dex.utils.Exceptions import DebuggerException
|
||||
from dex.utils.Timeout import Timeout
|
||||
|
||||
|
||||
class BreakpointRange:
|
||||
@@ -140,10 +141,26 @@ class ConditionalController(DebuggerControllerBase):
|
||||
time.sleep(self._pause_between_steps)
|
||||
|
||||
exit_desired = False
|
||||
timed_out = False
|
||||
total_timeout = Timeout(self.context.options.timeout_total)
|
||||
|
||||
while not self.debugger.is_finished:
|
||||
while self.debugger.is_running:
|
||||
pass
|
||||
|
||||
breakpoint_timeout = Timeout(self.context.options.timeout_breakpoint)
|
||||
while self.debugger.is_running and not timed_out:
|
||||
# Check to see whether we've timed out while we're waiting.
|
||||
if total_timeout.timed_out():
|
||||
self.context.logger.error('Debugger session has been '
|
||||
f'running for {total_timeout.elapsed}s, timeout reached!')
|
||||
timed_out = True
|
||||
if breakpoint_timeout.timed_out():
|
||||
self.context.logger.error(f'Debugger session has not '
|
||||
f'hit a breakpoint for {breakpoint_timeout.elapsed}s, timeout '
|
||||
'reached!')
|
||||
timed_out = True
|
||||
|
||||
if timed_out:
|
||||
break
|
||||
|
||||
step_info = self.debugger.get_step_info(self._watches, self._step_index)
|
||||
if step_info.current_frame:
|
||||
|
||||
@@ -13,6 +13,7 @@ import time
|
||||
from dex.debugger.DebuggerControllers.DebuggerControllerBase import DebuggerControllerBase
|
||||
from dex.debugger.DebuggerControllers.ControllerHelpers import in_source_file, update_step_watches
|
||||
from dex.utils.Exceptions import DebuggerException, LoadDebuggerException
|
||||
from dex.utils.Timeout import Timeout
|
||||
|
||||
class EarlyExitCondition(object):
|
||||
def __init__(self, on_line, hit_count, expression, values):
|
||||
@@ -81,12 +82,25 @@ class DefaultController(DebuggerControllerBase):
|
||||
self.watches.update(command_obj.get_watches())
|
||||
early_exit_conditions = self._get_early_exit_conditions()
|
||||
|
||||
timed_out = False
|
||||
total_timeout = Timeout(self.context.options.timeout_total)
|
||||
max_steps = self.context.options.max_steps
|
||||
for _ in range(max_steps):
|
||||
while self.debugger.is_running:
|
||||
pass
|
||||
|
||||
if self.debugger.is_finished:
|
||||
breakpoint_timeout = Timeout(self.context.options.timeout_breakpoint)
|
||||
while self.debugger.is_running and not timed_out:
|
||||
# Check to see whether we've timed out while we're waiting.
|
||||
if total_timeout.timed_out():
|
||||
self.context.logger.error('Debugger session has been '
|
||||
f'running for {total_timeout.elapsed}s, timeout reached!')
|
||||
timed_out = True
|
||||
if breakpoint_timeout.timed_out():
|
||||
self.context.logger.error(f'Debugger session has not '
|
||||
f'hit a breakpoint for {breakpoint_timeout.elapsed}s, timeout '
|
||||
'reached!')
|
||||
timed_out = True
|
||||
|
||||
if timed_out or self.debugger.is_finished:
|
||||
break
|
||||
|
||||
self.step_index += 1
|
||||
|
||||
@@ -121,7 +121,21 @@ def add_debugger_tool_arguments(parser, context, defaults):
|
||||
default='',
|
||||
help='command line arguments for the test program, in addition to any '
|
||||
'provided by DexCommandLine')
|
||||
|
||||
parser.add_argument(
|
||||
'--timeout-total',
|
||||
metavar='<seconds>',
|
||||
type=float,
|
||||
default=0.0,
|
||||
help='if >0, debugger session will automatically exit after '
|
||||
'running for <timeout-total> seconds')
|
||||
parser.add_argument(
|
||||
'--timeout-breakpoint',
|
||||
metavar='<seconds>',
|
||||
type=float,
|
||||
default=0.0,
|
||||
help='if >0, debugger session will automatically exit after '
|
||||
'waiting <timeout-breakpoint> seconds without hitting a '
|
||||
'breakpoint')
|
||||
|
||||
def handle_debugger_tool_base_options(context, defaults): # noqa
|
||||
options = context.options
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
# DExTer : Debugging Experience Tester
|
||||
# ~~~~~~ ~ ~~ ~ ~~
|
||||
#
|
||||
# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
# See https://llvm.org/LICENSE.txt for license information.
|
||||
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
"""Utility class to check for timeouts. Timer starts when the object is initialized,
|
||||
and can be checked by calling timed_out(). Passing a timeout value of 0.0 or less
|
||||
means a timeout will never be triggered, i.e. timed_out() will always return False.
|
||||
"""
|
||||
|
||||
import time
|
||||
|
||||
class Timeout(object):
|
||||
|
||||
def __init__(self, duration: float):
|
||||
self.start = self.now
|
||||
self.duration = duration
|
||||
|
||||
def timed_out(self):
|
||||
if self.duration <= 0.0:
|
||||
return False
|
||||
return self.elapsed > self.duration
|
||||
|
||||
@property
|
||||
def elapsed(self):
|
||||
return self.now - self.start
|
||||
|
||||
@property
|
||||
def now(self):
|
||||
return time.time()
|
||||
Reference in New Issue
Block a user