From 5100a38fcd9243d710145933eddf021dcc6e9ad5 Mon Sep 17 00:00:00 2001 From: Bob Lantz Date: Thu, 2 Aug 2018 06:58:33 -0700 Subject: [PATCH] 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. --- mininet/util.py | 31 ++++++++++++------------------- 1 file changed, 12 insertions(+), 19 deletions(-) diff --git a/mininet/util.py b/mininet/util.py index cb09f27..1881318 100644 --- a/mininet/util.py +++ b/mininet/util.py @@ -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: