Redesign pmonitor()

This is tricky to get right, but I think it is correct
to drain the buffers like this.
This commit is contained in:
Bob Lantz
2018-07-25 19:44:45 -07:00
parent 356b024d6b
commit f94ee8ec97
+13 -8
View File
@@ -412,6 +412,11 @@ def pmonitor(popens, timeoutms=500, readline=True,
# Use non-blocking reads # Use non-blocking reads
flags = fcntl( fd, F_GETFL ) flags = fcntl( fd, F_GETFL )
fcntl( fd, F_SETFL, flags | O_NONBLOCK ) fcntl( fd, F_SETFL, flags | O_NONBLOCK )
def readit( f ):
"Helper function - read line or data"
# Note this will block if readline is True
line = f.readline() if readline else f.read( readmax )
return decode( line )
while popens: while popens:
fds = poller.poll( timeoutms ) fds = poller.poll( timeoutms )
if fds: if fds:
@@ -419,15 +424,15 @@ def pmonitor(popens, timeoutms=500, readline=True,
host = fdToHost[ fd ] host = fdToHost[ fd ]
popen = popens[ host ] popen = popens[ host ]
if event & POLLIN: if event & POLLIN:
if readline: line = readit( popen.stdout )
# Attempt to read a line of output
# This blocks until we receive a newline!
line = decode( popen.stdout.readline() )
else:
line = decode( popen.stdout.read( readmax ) )
yield host, line yield host, line
# Check for EOF if event & POLLHUP:
elif event & POLLHUP: while True:
# Drain buffer
line = readit( popen.stdout )
yield host, line
if line == '':
break
poller.unregister( fd ) poller.unregister( fd )
del popens[ host ] del popens[ host ]
else: else: