Skip to content

Commit ee5617d

Browse files
committed
[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
1 parent 893ce57 commit ee5617d

File tree

4 files changed

+82
-6
lines changed

4 files changed

+82
-6
lines changed

cross-project-tests/debuginfo-tests/dexter/dex/debugger/DebuggerControllers/ConditionalController.py

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
from dex.debugger.DebuggerControllers.DebuggerControllerBase import DebuggerControllerBase
1717
from dex.debugger.DebuggerBase import DebuggerBase
1818
from dex.utils.Exceptions import DebuggerException
19+
from dex.utils.Timeout import Timeout
1920

2021

2122
class BreakpointRange:
@@ -140,10 +141,26 @@ def _run_debugger_custom(self, cmdline):
140141
time.sleep(self._pause_between_steps)
141142

142143
exit_desired = False
144+
timed_out = False
145+
total_timeout = Timeout(self.context.options.timeout_total)
143146

144147
while not self.debugger.is_finished:
145-
while self.debugger.is_running:
146-
pass
148+
149+
breakpoint_timeout = Timeout(self.context.options.timeout_breakpoint)
150+
while self.debugger.is_running and not timed_out:
151+
# Check to see whether we've timed out while we're waiting.
152+
if total_timeout.timed_out():
153+
self.context.logger.error('Debugger session has been '
154+
f'running for {total_timeout.elapsed}s, timeout reached!')
155+
timed_out = True
156+
if breakpoint_timeout.timed_out():
157+
self.context.logger.error(f'Debugger session has not '
158+
f'hit a breakpoint for {breakpoint_timeout.elapsed}s, timeout '
159+
'reached!')
160+
timed_out = True
161+
162+
if timed_out:
163+
break
147164

148165
step_info = self.debugger.get_step_info(self._watches, self._step_index)
149166
if step_info.current_frame:

cross-project-tests/debuginfo-tests/dexter/dex/debugger/DebuggerControllers/DefaultController.py

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
from dex.debugger.DebuggerControllers.DebuggerControllerBase import DebuggerControllerBase
1414
from dex.debugger.DebuggerControllers.ControllerHelpers import in_source_file, update_step_watches
1515
from dex.utils.Exceptions import DebuggerException, LoadDebuggerException
16+
from dex.utils.Timeout import Timeout
1617

1718
class EarlyExitCondition(object):
1819
def __init__(self, on_line, hit_count, expression, values):
@@ -81,12 +82,25 @@ def _run_debugger_custom(self, cmdline):
8182
self.watches.update(command_obj.get_watches())
8283
early_exit_conditions = self._get_early_exit_conditions()
8384

85+
timed_out = False
86+
total_timeout = Timeout(self.context.options.timeout_total)
8487
max_steps = self.context.options.max_steps
8588
for _ in range(max_steps):
86-
while self.debugger.is_running:
87-
pass
8889

89-
if self.debugger.is_finished:
90+
breakpoint_timeout = Timeout(self.context.options.timeout_breakpoint)
91+
while self.debugger.is_running and not timed_out:
92+
# Check to see whether we've timed out while we're waiting.
93+
if total_timeout.timed_out():
94+
self.context.logger.error('Debugger session has been '
95+
f'running for {total_timeout.elapsed}s, timeout reached!')
96+
timed_out = True
97+
if breakpoint_timeout.timed_out():
98+
self.context.logger.error(f'Debugger session has not '
99+
f'hit a breakpoint for {breakpoint_timeout.elapsed}s, timeout '
100+
'reached!')
101+
timed_out = True
102+
103+
if timed_out or self.debugger.is_finished:
90104
break
91105

92106
self.step_index += 1

cross-project-tests/debuginfo-tests/dexter/dex/debugger/Debuggers.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,21 @@ def add_debugger_tool_arguments(parser, context, defaults):
121121
default='',
122122
help='command line arguments for the test program, in addition to any '
123123
'provided by DexCommandLine')
124-
124+
parser.add_argument(
125+
'--timeout-total',
126+
metavar='<seconds>',
127+
type=float,
128+
default=0.0,
129+
help='if >0, debugger session will automatically exit after '
130+
'running for <timeout-total> seconds')
131+
parser.add_argument(
132+
'--timeout-breakpoint',
133+
metavar='<seconds>',
134+
type=float,
135+
default=0.0,
136+
help='if >0, debugger session will automatically exit after '
137+
'waiting <timeout-breakpoint> seconds without hitting a '
138+
'breakpoint')
125139

126140
def handle_debugger_tool_base_options(context, defaults): # noqa
127141
options = context.options
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# DExTer : Debugging Experience Tester
2+
# ~~~~~~ ~ ~~ ~ ~~
3+
#
4+
# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5+
# See https://llvm.org/LICENSE.txt for license information.
6+
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7+
"""Utility class to check for timeouts. Timer starts when the object is initialized,
8+
and can be checked by calling timed_out(). Passing a timeout value of 0.0 or less
9+
means a timeout will never be triggered, i.e. timed_out() will always return False.
10+
"""
11+
12+
import time
13+
14+
class Timeout(object):
15+
16+
def __init__(self, duration: float):
17+
self.start = self.now
18+
self.duration = duration
19+
20+
def timed_out(self):
21+
if self.duration <= 0.0:
22+
return False
23+
return self.elapsed > self.duration
24+
25+
@property
26+
def elapsed(self):
27+
return self.now - self.start
28+
29+
@property
30+
def now(self):
31+
return time.time()

0 commit comments

Comments
 (0)