reduce.py: improved --segfault / added detection of "hang" caused by reduced code / cleanups (#3693)

This commit is contained in:
Oliver Stöneberg 2022-01-12 22:26:32 +01:00 committed by GitHub
parent 59837be152
commit 4f508c93c4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 34 additions and 6 deletions

View File

@ -1,7 +1,9 @@
#!/usr/bin/env python #!/usr/bin/env python
import subprocess import subprocess
import sys import sys
import time
# TODO: add --hang option to detect code which impacts the analysis time
def show_syntax(): def show_syntax():
print('Syntax:') print('Syntax:')
print(' reduce.py --cmd=<full command> --expected=<expected text output> --file=<source file> [--segfault]') print(' reduce.py --cmd=<full command> --expected=<expected text output> --file=<source file> [--segfault]')
@ -17,7 +19,9 @@ CMD = None
EXPECTED = None EXPECTED = None
SEGFAULT = False SEGFAULT = False
FILE = None FILE = None
ORGFILE = None
BACKUPFILE = None BACKUPFILE = None
TIMEOUTFILE = None
for arg in sys.argv[1:]: for arg in sys.argv[1:]:
if arg.startswith('--cmd='): if arg.startswith('--cmd='):
CMD = arg[arg.find('=') + 1:] CMD = arg[arg.find('=') + 1:]
@ -25,7 +29,9 @@ for arg in sys.argv[1:]:
EXPECTED = arg[arg.find('=') + 1:] EXPECTED = arg[arg.find('=') + 1:]
elif arg.startswith('--file='): elif arg.startswith('--file='):
FILE = arg[arg.find('=') + 1:] FILE = arg[arg.find('=') + 1:]
ORGFILE = FILE + '.org'
BACKUPFILE = FILE + '.bak' BACKUPFILE = FILE + '.bak'
TIMEOUTFILE = FILE + '.timeout'
elif arg == '--segfault': elif arg == '--segfault':
SEGFAULT = True SEGFAULT = True
@ -37,6 +43,11 @@ if not SEGFAULT and EXPECTED is None:
print('Abort: No --expected') print('Abort: No --expected')
show_syntax() show_syntax()
# need to add '--error-exitcode=0' so detected issues will not be interpreted as a crash
if SEGFAULT and not '--error-exitcode=0' in CMD:
print("Adding '--error-exitcode=0' to --cmd")
CMD = CMD + ' --error-exitcode=0'
if FILE is None: if FILE is None:
print('Abort: No --file') print('Abort: No --file')
show_syntax() show_syntax()
@ -49,9 +60,22 @@ else:
print('FILE=' + FILE) print('FILE=' + FILE)
def runtool(): def runtool(filedata=None):
timeout = None
if elapsed_time:
timeout = elapsed_time * 2
p = subprocess.Popen(CMD.split(), stdout=subprocess.PIPE, stderr=subprocess.PIPE) p = subprocess.Popen(CMD.split(), stdout=subprocess.PIPE, stderr=subprocess.PIPE)
comm = p.communicate() try:
comm = p.communicate(timeout=timeout)
except subprocess.TimeoutExpired:
print('timeout')
p.kill()
p.communicate()
if filedata:
writefile(TIMEOUTFILE, filedata)
return False
#print(p.returncode)
#print(comm)
if SEGFAULT: if SEGFAULT:
if p.returncode != 0: if p.returncode != 0:
return True return True
@ -78,7 +102,7 @@ def replaceandrun(what, filedata, i, line):
bak = filedata[i] bak = filedata[i]
filedata[i] = line filedata[i] = line
writefile(FILE, filedata) writefile(FILE, filedata)
if runtool(): if runtool(filedata):
print('pass') print('pass')
writefile(BACKUPFILE, filedata) writefile(BACKUPFILE, filedata)
return True return True
@ -94,7 +118,7 @@ def replaceandrun2(what, filedata, i, line1, line2):
filedata[i] = line1 filedata[i] = line1
filedata[i + 1] = line2 filedata[i + 1] = line2
writefile(FILE, filedata) writefile(FILE, filedata)
if runtool(): if runtool(filedata):
print('pass') print('pass')
writefile(BACKUPFILE, filedata) writefile(BACKUPFILE, filedata)
else: else:
@ -111,7 +135,7 @@ def clearandrun(what, filedata, i1, i2):
filedata2[i] = '' filedata2[i] = ''
i = i + 1 i = i + 1
writefile(FILE, filedata2) writefile(FILE, filedata2)
if runtool(): if runtool(filedata2):
print('pass') print('pass')
writefile(BACKUPFILE, filedata2) writefile(BACKUPFILE, filedata2)
return filedata2 return filedata2
@ -249,15 +273,19 @@ def removeline(filedata):
# reduce.. # reduce..
print('Make sure error can be reproduced...') print('Make sure error can be reproduced...')
elapsed_time = None
t = time.perf_counter()
if not runtool(): if not runtool():
print("Cannot reproduce") print("Cannot reproduce")
sys.exit(1) sys.exit(1)
elapsed_time = time.perf_counter() - t
print('elapsed_time: {}'.format(elapsed_time))
f = open(FILE, 'rt') f = open(FILE, 'rt')
filedata = f.readlines() filedata = f.readlines()
f.close() f.close()
writefile(BACKUPFILE, filedata) writefile(ORGFILE, filedata)
while True: while True:
filedata1 = list(filedata) filedata1 = list(filedata)