11#!/usr/bin/env python
22import subprocess
33import sys
4+ import time
45
6+ # TODO: add --hang option to detect code which impacts the analysis time
57def 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():
1719EXPECTED = None
1820SEGFAULT = False
1921FILE = None
22+ ORGFILE = None
2023BACKUPFILE = None
24+ TIMEOUTFILE = None
2125for 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+
4051if FILE is None :
4152 print ('Abort: No --file' )
4253 show_syntax ()
@@ -49,9 +60,22 @@ def show_syntax():
4960print ('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..
251275print ('Make sure error can be reproduced...' )
276+ elapsed_time = None
277+ t = time .perf_counter ()
252278if 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
256284f = open (FILE , 'rt' )
257285filedata = f .readlines ()
258286f .close ()
259287
260- writefile (BACKUPFILE , filedata )
288+ writefile (ORGFILE , filedata )
261289
262290while True :
263291 filedata1 = list (filedata )
0 commit comments