88import sys
99import select
1010import logging
11+ import threading
1112from subprocess import (
1213call ,
1314Popen ,
@@ -72,22 +73,31 @@ def read_line_slow(stream):
7273return line
7374# end
7475
75- fdmap = {process .stdout .fileno () : (process .stdout ,stdout_handler ,read_line_fast ),
76- process .stderr .fileno () : (process .stderr ,stderr_handler ,read_line_slow ) }
77-
78- if hasattr (select ,'poll' ):
79- def dispatch_line (fd ):
80- stream ,handler ,readline = fdmap [fd ]
76+ def dispatch_line (fno ):
77+ stream ,handler ,readline = fdmap [fno ]
8178# this can possibly block for a while, but since we wake-up with at least one or more lines to handle,
8279# we are good ...
8380line = readline (stream ).decode (defenc )
8481if line and handler :
8582handler (line )
8683return line
8784# end dispatch helper
85+ # end
86+
87+ def deplete_buffer (fno ):
88+ while True :
89+ line = dispatch_line (fno )
90+ if not line :
91+ break
92+ # end deplete buffer
93+ # end
94+
95+ fdmap = {process .stdout .fileno () : (process .stdout ,stdout_handler ,read_line_fast ),
96+ process .stderr .fileno () : (process .stderr ,stderr_handler ,read_line_slow ) }
8897
89- # poll is preferred, as select is limited to file handles up to 1024 ... . Not an issue for us though,
90- # as we deal with relatively blank processes
98+ if hasattr (select ,'poll' ):
99+ # poll is preferred, as select is limited to file handles up to 1024 ... . This could otherwise be
100+ # an issue for us, as it matters how many handles or own process has
91101poll = select .poll ()
92102READ_ONLY = select .POLLIN | select .POLLPRI | select .POLLHUP | select .POLLERR
93103CLOSED = select .POLLHUP | select .POLLERR
@@ -113,18 +123,23 @@ def dispatch_line(fd):
113123# end endless loop
114124
115125# Depelete all remaining buffers
116- for fno ,_ in fdmap .items ():
117- while True :
118- line = dispatch_line (fno )
119- if not line :
120- break
121- # end deplete buffer
126+ for fno in fdmap .keys ():
127+ deplete_buffer (fno )
122128# end for each file handle
123129else :
124130# Oh ... probably we are on windows. select.select() can only handle sockets, we have files
125131# The only reliable way to do this now is to use threads and wait for both to finish
126132# Since the finalizer is expected to wait, we don't have to introduce our own wait primitive
127- raise NotImplementedError ()
133+ # NO: It's not enough unfortunately, and we will have to sync the threads
134+ threads = list ()
135+ for fno in fdmap .keys ():
136+ t = threading .Thread (target = lambda :deplete_buffer (fno ))
137+ threads .append (t )
138+ t .start ()
139+ # end
140+ for t in threads :
141+ t .join ()
142+ # end
128143# end
129144
130145return finalizer (process )