pmonitor() fixes
pmonitor() is hard to get right, but this seems like a reasonable improvement: 1. non-blocking I/O so we can drain buffer with impunity 2. drain buffer after poll 3. unregister fd on POLLHUP Note we may have a unicode splitting problem since we're decoding chunks of bytes, but that is a problem for another day I think.
This commit is contained in:
+12
-19
@@ -416,34 +416,27 @@ def pmonitor(popens, timeoutms=500, readline=True,
|
||||
for host, popen in popens.items():
|
||||
fd = popen.stdout.fileno()
|
||||
fdToHost[ fd ] = host
|
||||
poller.register( fd, POLLIN )
|
||||
if not readline:
|
||||
# Use non-blocking reads
|
||||
flags = fcntl( fd, F_GETFL )
|
||||
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 )
|
||||
|
||||
poller.register( fd, POLLIN | POLLHUP )
|
||||
flags = fcntl( fd, F_GETFL )
|
||||
fcntl( fd, F_SETFL, flags | O_NONBLOCK )
|
||||
while popens:
|
||||
fds = poller.poll( timeoutms )
|
||||
if fds:
|
||||
for fd, event in fds:
|
||||
host = fdToHost[ fd ]
|
||||
popen = popens[ host ]
|
||||
if event & POLLIN:
|
||||
line = readit( popen.stdout )
|
||||
yield host, line
|
||||
if event & POLLHUP:
|
||||
if event & POLLIN or event & POLLHUP:
|
||||
while True:
|
||||
# Drain buffer
|
||||
line = readit( popen.stdout )
|
||||
yield host, line
|
||||
try:
|
||||
f = popen.stdout
|
||||
line = decode( f.readline() if readline
|
||||
else f.read( readmax ) )
|
||||
except IOError:
|
||||
line = ''
|
||||
if line == '':
|
||||
break
|
||||
yield host, line
|
||||
if event & POLLHUP:
|
||||
poller.unregister( fd )
|
||||
del popens[ host ]
|
||||
else:
|
||||
|
||||
Reference in New Issue
Block a user