Skip to content

Commit 3a341f7

Browse files
author
Julien Gilli
committed
test: add --abort-on-timeout option to test.py
Currently, when a process times out, it is terminated by sending it the SIGTERM signal. Sending SIGBART instead allows the operating system to generate a core file that can be investigated later using post-mortem debuggers such as llnode or mdb_v8. This can be very useful when investigating flaky tests that time out, since in that case the failure is difficult to reproduce, and being able to look at a core file makes a big difference. With these changes, passing the --abort-on-timeout command line option to tools/test.py now sends SIGABRT to processes timing out on all platforms but Windows. PR-URL: #11086 Ref: #11026 Reviewed-By: James M Snell <[email protected]> Reviewed-By: Gibson Fahnestock <[email protected]> Reviewed-By: Sakthipriyan Vairamani <[email protected]> Reviewed-By: Santiago Gimeno <[email protected]> Reviewed-By: Ben Noordhuis <[email protected]> Reviewed-By: Colin Ihrig <[email protected]> Reviewed-By: Michael Dawson <[email protected]> Reviewed-By: Anna Henningsen <[email protected]>
1 parent 6034bdc commit 3a341f7

File tree

1 file changed

+22
-6
lines changed

1 file changed

+22
-6
lines changed

tools/test.py

+22-6
Original file line numberDiff line numberDiff line change
@@ -564,11 +564,11 @@ def HasFailed(self):
564564
return execution_failed
565565

566566

567-
def KillProcessWithID(pid):
567+
def KillProcessWithID(pid, signal_to_send=signal.SIGTERM):
568568
if utils.IsWindows():
569569
os.popen('taskkill /T /F /PID %d' % pid)
570570
else:
571-
os.kill(pid, signal.SIGTERM)
571+
os.kill(pid, signal_to_send)
572572

573573

574574
MAX_SLEEP_TIME = 0.1
@@ -587,6 +587,17 @@ def Win32SetErrorMode(mode):
587587
pass
588588
return prev_error_mode
589589

590+
591+
def KillTimedOutProcess(context, pid):
592+
signal_to_send = signal.SIGTERM
593+
if context.abort_on_timeout:
594+
# Using SIGABRT here allows the OS to generate a core dump that can be
595+
# looked at post-mortem, which helps for investigating failures that are
596+
# difficult to reproduce.
597+
signal_to_send = signal.SIGABRT
598+
KillProcessWithID(pid, signal_to_send)
599+
600+
590601
def RunProcess(context, timeout, args, **rest):
591602
if context.verbose: print "#", " ".join(args)
592603
popen_args = args
@@ -626,7 +637,7 @@ def RunProcess(context, timeout, args, **rest):
626637
while True:
627638
if time.time() >= end_time:
628639
# Kill the process and wait for it to exit.
629-
KillProcessWithID(process.pid)
640+
KillTimedOutProcess(context, process.pid)
630641
exit_code = process.wait()
631642
timed_out = True
632643
break
@@ -647,7 +658,7 @@ def RunProcess(context, timeout, args, **rest):
647658
while exit_code is None:
648659
if (not end_time is None) and (time.time() >= end_time):
649660
# Kill the process and wait for it to exit.
650-
KillProcessWithID(process.pid)
661+
KillTimedOutProcess(context, process.pid)
651662
exit_code = process.wait()
652663
timed_out = True
653664
else:
@@ -855,7 +866,7 @@ class Context(object):
855866

856867
def __init__(self, workspace, buildspace, verbose, vm, expect_fail,
857868
timeout, processor, suppress_dialogs,
858-
store_unexpected_output, repeat):
869+
store_unexpected_output, repeat, abort_on_timeout):
859870
self.workspace = workspace
860871
self.buildspace = buildspace
861872
self.verbose = verbose
@@ -866,6 +877,7 @@ def __init__(self, workspace, buildspace, verbose, vm, expect_fail,
866877
self.suppress_dialogs = suppress_dialogs
867878
self.store_unexpected_output = store_unexpected_output
868879
self.repeat = repeat
880+
self.abort_on_timeout = abort_on_timeout
869881

870882
def GetVm(self, arch, mode):
871883
if arch == 'none':
@@ -1400,6 +1412,9 @@ def BuildOptions():
14001412
result.add_option('--repeat',
14011413
help='Number of times to repeat given tests',
14021414
default=1, type="int")
1415+
result.add_option('--abort-on-timeout',
1416+
help='Send SIGABRT instead of SIGTERM to kill processes that time out',
1417+
default=False, dest="abort_on_timeout")
14031418
return result
14041419

14051420

@@ -1579,7 +1594,8 @@ def Main():
15791594
processor,
15801595
options.suppress_dialogs,
15811596
options.store_unexpected_output,
1582-
options.repeat)
1597+
options.repeat,
1598+
options.abort_on_timeout)
15831599
# First build the required targets
15841600
if not options.no_build:
15851601
reqs = [ ]

0 commit comments

Comments
 (0)