Skip to content

Commit 2677261

Browse files
authored
Add timeout to Fuzzlyn reductions (#115189)
1 parent dbb3f75 commit 2677261

File tree

2 files changed

+40
-19
lines changed

2 files changed

+40
-19
lines changed

src/coreclr/scripts/fuzzlyn_run.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ def run(self):
119119

120120
if new_line:
121121
evt = json.loads(new_line)
122-
# Only reduce BadResult examples since crashes take very long to reduce.
122+
# Do not reduce crash examples since those take a very long to reduce.
123123
# We will still report crashes, just not with a reduced example.
124124
if evt["Kind"] == "ExampleFound":
125125
ex = evt["Example"]
@@ -147,7 +147,7 @@ def run(self):
147147
"--seed", str(ex['Seed']),
148148
"--collect-spmi-to", spmi_collections_path,
149149
"--output", output_path]
150-
run_command(cmd)
150+
run_command(cmd, _timeout=60*25)
151151
if path.exists(output_path):
152152
num_reduced += 1
153153
if num_reduced >= 5:
@@ -156,6 +156,8 @@ def run(self):
156156

157157
if ex_assert_err is not None:
158158
self.reduced_jit_asserts.add(ex_assert_err)
159+
else:
160+
print(" Reduction failed, output file not present")
159161

160162

161163
def main(main_args):

src/coreclr/scripts/jitutil.py

Lines changed: 36 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import logging
2121
import time
2222
import tarfile
23+
import threading
2324
import urllib
2425
import urllib.request
2526
import zipfile
@@ -129,7 +130,7 @@ def decode_and_print(str_to_decode):
129130
return output
130131

131132

132-
def run_command(command_to_run, _cwd=None, _exit_on_fail=False, _output_file=None, _env=None):
133+
def run_command(command_to_run, _cwd=None, _exit_on_fail=False, _output_file=None, _env=None, _timeout=None):
133134
""" Runs the command.
134135
135136
Args:
@@ -138,6 +139,7 @@ def run_command(command_to_run, _cwd=None, _exit_on_fail=False, _output_file=Non
138139
_exit_on_fail (bool): If it should exit on failure.
139140
_output_file ():
140141
_env: environment for sub-process, passed to subprocess.Popen()
142+
_timeout: timeout in seconds, or None for no timeout
141143
Returns:
142144
(string, string, int): Returns a tuple of stdout, stderr, and command return code if _output_file= None
143145
Otherwise stdout, stderr are empty.
@@ -156,27 +158,44 @@ def run_command(command_to_run, _cwd=None, _exit_on_fail=False, _output_file=Non
156158
output_type = subprocess.STDOUT if _output_file else subprocess.PIPE
157159
with subprocess.Popen(command_to_run, env=_env, stdout=subprocess.PIPE, stderr=output_type, cwd=_cwd) as proc:
158160

159-
# For long running command, continuously print the output
160-
if _output_file:
161-
while True:
162-
with open(_output_file, 'a') as of:
163-
output = proc.stdout.readline()
164-
if proc.poll() is not None:
165-
break
166-
if output:
167-
output_str = decode_and_print(output.strip())
168-
of.write(output_str + "\n")
169-
else:
170-
command_stdout, command_stderr = proc.communicate()
171-
if len(command_stdout) > 0:
172-
decode_and_print(command_stdout)
173-
if len(command_stderr) > 0:
174-
decode_and_print(command_stderr)
161+
timer = None
162+
if _timeout is not None:
163+
def try_kill():
164+
try:
165+
print(" Timeout reached; killing process")
166+
proc.kill()
167+
except:
168+
pass
169+
170+
timer = threading.Timer(_timeout, try_kill)
171+
timer.start()
172+
173+
try:
174+
# For long running command, continuously print the output
175+
if _output_file:
176+
while True:
177+
with open(_output_file, 'a') as of:
178+
output = proc.stdout.readline()
179+
if proc.poll() is not None:
180+
break
181+
if output:
182+
output_str = decode_and_print(output.strip())
183+
of.write(output_str + "\n")
184+
else:
185+
command_stdout, command_stderr = proc.communicate()
186+
if len(command_stdout) > 0:
187+
decode_and_print(command_stdout)
188+
if len(command_stderr) > 0:
189+
decode_and_print(command_stderr)
190+
finally:
191+
if timer:
192+
timer.cancel()
175193

176194
return_code = proc.returncode
177195
if _exit_on_fail and return_code != 0:
178196
print("Command failed. Exiting.")
179197
sys.exit(1)
198+
180199
return command_stdout, command_stderr, return_code
181200

182201

0 commit comments

Comments
 (0)