From 4065511abb945c793187b23afc82590d7c966c84 Mon Sep 17 00:00:00 2001 From: Bob Lantz <rlantz@cs.stanford.edu> Date: Thu, 11 Mar 2010 16:58:12 -0800 Subject: [PATCH] Detach shells from tty; monitoring changes. Call netns using setsid to detach from the tty; this is intended to fix the problem of control-C killing your network. sendInt() doesn't actually work - hopefully we can fix this in the future, but it's tricky since we want to detach the many shells from our tty, but then optionally send tty interrupts to them! Ideally we would either know the pid of the subprocess or be able to send a signal to bash to get it to interrupt its subprocess. waitOutput() now uses monitor. We also handle sentinels coming in the middle of output (but default at end should still work well.) --- mininet/node.py | 35 ++++++++++++++++------------------- 1 file changed, 16 insertions(+), 19 deletions(-) diff --git a/mininet/node.py b/mininet/node.py index 718d04da..8dd13f71 100644 --- a/mininet/node.py +++ b/mininet/node.py @@ -66,8 +66,9 @@ def __init__( self, name, inNamespace=True, defaultIP: default IP address for intf 0""" self.name = name closeFds = False # speed vs. memory use + # setsid is necessary to detach from tty # xpg_echo is needed so we can echo our sentinel in sendCmd - cmd = [ '/bin/bash', '-O', 'xpg_echo' ] + cmd = [ '/usr/bin/setsid', '/bin/bash', '-O', 'xpg_echo' ] self.inNamespace = inNamespace if self.inNamespace: cmd = [ 'netns' ] + cmd @@ -143,20 +144,22 @@ def sendCmd( self, cmd ): self.write( cmd + separator + ' echo -n "\\0177" \n' ) self.waiting = True + def sendInt( self ): + """Placeholder for function to interrupt running subprocess. + This is a tricky problem to solve.""" + self.write( chr( 3 ) ) + def monitor( self ): "Monitor the output of a command, returning (done?, data)." assert self.waiting self.waitReadable() data = self.read( 1024 ) - if len( data ) > 0 and data[ -1 ] == chr( 0177 ): + if len( data ) > 0 and data[ -1 ] == chr( 127 ): self.waiting = False return True, data[ :-1 ] - else: - return False, data - - def sendInt( self ): - "Send ^C, hopefully interrupting an interactive subprocess." - self.write( chr( 3 ) ) + elif chr( 127 ) in data: + return True, data.replace( chr( 127 ), '' ) + return False, data def waitOutput( self, verbose=False ): """Wait for a command to complete. @@ -165,18 +168,12 @@ def waitOutput( self, verbose=False ): the output, including trailing newline. verbose: print output interactively""" log = info if verbose else debug - assert self.waiting output = '' - while True: - self.waitReadable() - data = self.read( 1024 ) - if len( data ) > 0 and data[ -1 ] == chr( 0177 ): - output += data[ :-1 ] - log( output ) - break - else: - output += data - self.waiting = False + done = False + while not done: + done, data = self.monitor() + output += data + log( data ) return output def cmd( self, cmd, verbose=False ): -- GitLab