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.)
This commit is contained in:
Bob Lantz
2010-03-11 17:16:27 -08:00
parent 9f32a08b28
commit 9dbe572abe
+14 -17
View File
@@ -66,8 +66,9 @@ class Node( object ):
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,21 +144,23 @@ class Node( object ):
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:
elif chr( 127 ) in data:
return True, data.replace( chr( 127 ), '' )
return False, data
def sendInt( self ):
"Send ^C, hopefully interrupting an interactive subprocess."
self.write( chr( 3 ) )
def waitOutput( self, verbose=False ):
"""Wait for a command to complete.
Completion is signaled by a sentinel character, ASCII(127)
@@ -165,18 +168,12 @@ class Node( object ):
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:
done = False
while not done:
done, data = self.monitor()
output += data
self.waiting = False
log( data )
return output
def cmd( self, cmd, verbose=False ):