Skip to content

Commit 4f508c9

Browse files
authored
reduce.py: improved --segfault / added detection of "hang" caused by reduced code / cleanups (danmar#3693)
1 parent 59837be commit 4f508c9

File tree

1 file changed

+34
-6
lines changed

1 file changed

+34
-6
lines changed

tools/reduce.py

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
#!/usr/bin/env python
22
import subprocess
33
import sys
4+
import time
45

6+
# TODO: add --hang option to detect code which impacts the analysis time
57
def show_syntax():
68
print('Syntax:')
79
print(' reduce.py --cmd=<full command> --expected=<expected text output> --file=<source file> [--segfault]')
@@ -17,15 +19,19 @@ def show_syntax():
1719
EXPECTED = None
1820
SEGFAULT = False
1921
FILE = None
22+
ORGFILE = None
2023
BACKUPFILE = None
24+
TIMEOUTFILE = None
2125
for arg in sys.argv[1:]:
2226
if arg.startswith('--cmd='):
2327
CMD = arg[arg.find('=') + 1:]
2428
elif arg.startswith('--expected='):
2529
EXPECTED = arg[arg.find('=') + 1:]
2630
elif arg.startswith('--file='):
2731
FILE = arg[arg.find('=') + 1:]
32+
ORGFILE = FILE + '.org'
2833
BACKUPFILE = FILE + '.bak'
34+
TIMEOUTFILE = FILE + '.timeout'
2935
elif arg == '--segfault':
3036
SEGFAULT = True
3137

@@ -37,6 +43,11 @@ def show_syntax():
3743
print('Abort: No --expected')
3844
show_syntax()
3945

46+
# need to add '--error-exitcode=0' so detected issues will not be interpreted as a crash
47+
if SEGFAULT and not '--error-exitcode=0' in CMD:
48+
print("Adding '--error-exitcode=0' to --cmd")
49+
CMD = CMD + ' --error-exitcode=0'
50+
4051
if FILE is None:
4152
print('Abort: No --file')
4253
show_syntax()
@@ -49,9 +60,22 @@ def show_syntax():
4960
print('FILE=' + FILE)
5061

5162

52-
def runtool():
63+
def runtool(filedata=None):
64+
timeout = None
65+
if elapsed_time:
66+
timeout = elapsed_time * 2
5367
p = subprocess.Popen(CMD.split(), stdout=subprocess.PIPE, stderr=subprocess.PIPE)
54-
comm = p.communicate()
68+
try:
69+
comm = p.communicate(timeout=timeout)
70+
except subprocess.TimeoutExpired:
71+
print('timeout')
72+
p.kill()
73+
p.communicate()
74+
if filedata:
75+
writefile(TIMEOUTFILE, filedata)
76+
return False
77+
#print(p.returncode)
78+
#print(comm)
5579
if SEGFAULT:
5680
if p.returncode != 0:
5781
return True
@@ -78,7 +102,7 @@ def replaceandrun(what, filedata, i, line):
78102
bak = filedata[i]
79103
filedata[i] = line
80104
writefile(FILE, filedata)
81-
if runtool():
105+
if runtool(filedata):
82106
print('pass')
83107
writefile(BACKUPFILE, filedata)
84108
return True
@@ -94,7 +118,7 @@ def replaceandrun2(what, filedata, i, line1, line2):
94118
filedata[i] = line1
95119
filedata[i + 1] = line2
96120
writefile(FILE, filedata)
97-
if runtool():
121+
if runtool(filedata):
98122
print('pass')
99123
writefile(BACKUPFILE, filedata)
100124
else:
@@ -111,7 +135,7 @@ def clearandrun(what, filedata, i1, i2):
111135
filedata2[i] = ''
112136
i = i + 1
113137
writefile(FILE, filedata2)
114-
if runtool():
138+
if runtool(filedata2):
115139
print('pass')
116140
writefile(BACKUPFILE, filedata2)
117141
return filedata2
@@ -249,15 +273,19 @@ def removeline(filedata):
249273

250274
# reduce..
251275
print('Make sure error can be reproduced...')
276+
elapsed_time = None
277+
t = time.perf_counter()
252278
if not runtool():
253279
print("Cannot reproduce")
254280
sys.exit(1)
281+
elapsed_time = time.perf_counter() - t
282+
print('elapsed_time: {}'.format(elapsed_time))
255283

256284
f = open(FILE, 'rt')
257285
filedata = f.readlines()
258286
f.close()
259287

260-
writefile(BACKUPFILE, filedata)
288+
writefile(ORGFILE, filedata)
261289

262290
while True:
263291
filedata1 = list(filedata)

0 commit comments

Comments
 (0)