14
14
import time
15
15
import psutil
16
16
17
- def wait_timeout (proc , seconds ):
18
- """Wait for a process to finish, or raise exception after timeout"""
19
- start = time .time ()
20
- end = start + seconds
21
- interval = min (seconds / 1000.0 , .25 )
22
-
23
- while True :
24
- result = proc .poll ()
25
- if result is not None :
26
- return result
27
- if time .time () >= end :
28
- raise RuntimeError ("Process timed out" )
29
- time .sleep (interval )
30
-
31
17
def kill (proc_pid ):
32
18
process = psutil .Process (proc_pid )
33
19
for proc in process .children (recursive = True ):
@@ -54,6 +40,67 @@ def cleanup_processes():
54
40
55
41
testpath = os .path .dirname (__file__ )
56
42
43
+ from threading import Thread
44
+ from Queue import Queue , Empty
45
+
46
+ class NonBlockingStreamReader :
47
+
48
+ def __init__ (self , stream ):
49
+ '''
50
+ stream: the stream to read from.
51
+ Usually a process' stdout or stderr.
52
+ '''
53
+
54
+ self ._s = stream
55
+ self ._q = Queue ()
56
+
57
+ def _populateQueue (stream , queue ):
58
+ '''
59
+ Collect lines from 'stream' and put them in 'quque'.
60
+ '''
61
+
62
+ while True :
63
+ line = stream .readline ()
64
+ if line :
65
+ queue .put (line )
66
+ else :
67
+ break
68
+
69
+ self ._t = Thread (target = _populateQueue ,
70
+ args = (self ._s , self ._q ))
71
+ self ._t .daemon = True
72
+ self ._t .start () #start collecting lines from the stream
73
+
74
+ def readline (self , timeout = None ):
75
+ try :
76
+ return self ._q .get (block = timeout is not None ,
77
+ timeout = timeout )
78
+ except Empty :
79
+ return None
80
+
81
+ class UnexpectedEndOfStream (Exception ):
82
+ pass
83
+
84
+ def wait_timeout (proc , seconds , verbose ):
85
+ """Wait for a process to finish, or raise exception after timeout"""
86
+ start = time .time ()
87
+ end = start + seconds
88
+ interval = min (seconds / 1000.0 , .25 )
89
+
90
+ stdout = NonBlockingStreamReader (proc .stdout )
91
+ while True :
92
+ # Read text in verbose mode. Also sleep for a bit.
93
+ nextline = stdout .readline (interval )
94
+ if nextline and verbose :
95
+ sys .stdout .write (nextline )
96
+ sys .stdout .flush ()
97
+
98
+ # Poll for end of text.
99
+ result = proc .poll ()
100
+ if result is not None :
101
+ return result
102
+ if time .time () >= end :
103
+ raise RuntimeError ("Process timed out" )
57
104
58
105
def wrap_fd (pipeout ):
59
106
# Prepare to pass to child process
@@ -112,11 +159,13 @@ def lets_run_a_test(name):
112
159
sys .stdout .flush ()
113
160
sys .stderr .flush ()
114
161
115
- mavproxy_verbose = False
162
+ mavproxy_verbose = os . environ . get ( 'TEST_VERBOSE' , '0' ) != '0'
116
163
timeout = 5 * 60
117
164
118
165
try :
119
- p = Popen ([sys .executable , '-m' , 'MAVProxy.mavproxy' , '--logfile=' + tempfile .mkstemp ()[1 ], '--master=tcp:127.0.0.1:5760' ], cwd = testpath , env = newenv , stdin = PIPE , stdout = PIPE , stderr = PIPE if not mavproxy_verbose else None )
166
+ p = Popen ([sys .executable , '-m' , 'MAVProxy.mavproxy' , '--logfile=' + tempfile .mkstemp ()[1 ], '--master=tcp:127.0.0.1:5760' ],
167
+ cwd = testpath , env = newenv , stdin = PIPE , stdout = PIPE ,
168
+ stderr = PIPE if not mavproxy_verbose else None )
120
169
bg .append (p )
121
170
122
171
# TODO this sleep is only for us to waiting until
@@ -144,15 +193,7 @@ def lets_run_a_test(name):
144
193
p .stdin .write ('api start testlib.py\n ' )
145
194
p .stdin .flush ()
146
195
147
- if mavproxy_verbose :
148
- while True :
149
- nextline = p .stdout .readline ()
150
- if nextline == '' and p .poll () != None :
151
- break
152
- sys .stdout .write (nextline )
153
- sys .stdout .flush ()
154
- else :
155
- wait_timeout (p , timeout )
196
+ wait_timeout (p , timeout , mavproxy_verbose )
156
197
except RuntimeError :
157
198
kill (p .pid )
158
199
p .returncode = 143
0 commit comments