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():
|
for host, popen in popens.items():
|
||||||
fd = popen.stdout.fileno()
|
fd = popen.stdout.fileno()
|
||||||
fdToHost[ fd ] = host
|
fdToHost[ fd ] = host
|
||||||
poller.register( fd, POLLIN )
|
poller.register( fd, POLLIN | POLLHUP )
|
||||||
if not readline:
|
flags = fcntl( fd, F_GETFL )
|
||||||
# Use non-blocking reads
|
fcntl( fd, F_SETFL, flags | O_NONBLOCK )
|
||||||
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 )
|
|
||||||
|
|
||||||
while popens:
|
while popens:
|
||||||
fds = poller.poll( timeoutms )
|
fds = poller.poll( timeoutms )
|
||||||
if fds:
|
if fds:
|
||||||
for fd, event in fds:
|
for fd, event in fds:
|
||||||
host = fdToHost[ fd ]
|
host = fdToHost[ fd ]
|
||||||
popen = popens[ host ]
|
popen = popens[ host ]
|
||||||
if event & POLLIN:
|
if event & POLLIN or event & POLLHUP:
|
||||||
line = readit( popen.stdout )
|
|
||||||
yield host, line
|
|
||||||
if event & POLLHUP:
|
|
||||||
while True:
|
while True:
|
||||||
# Drain buffer
|
try:
|
||||||
line = readit( popen.stdout )
|
f = popen.stdout
|
||||||
yield host, line
|
line = decode( f.readline() if readline
|
||||||
|
else f.read( readmax ) )
|
||||||
|
except IOError:
|
||||||
|
line = ''
|
||||||
if line == '':
|
if line == '':
|
||||||
break
|
break
|
||||||
|
yield host, line
|
||||||
|
if event & POLLHUP:
|
||||||
poller.unregister( fd )
|
poller.unregister( fd )
|
||||||
del popens[ host ]
|
del popens[ host ]
|
||||||
else:
|
else:
|
||||||
|
|||||||
Reference in New Issue
Block a user