Skip to content
Snippets Groups Projects
Commit 4065511a authored by Bob Lantz's avatar Bob Lantz
Browse files

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.)
parent 2ad03eea
No related branches found
No related tags found
No related merge requests found
...@@ -66,8 +66,9 @@ def __init__( self, name, inNamespace=True, ...@@ -66,8 +66,9 @@ def __init__( self, name, inNamespace=True,
defaultIP: default IP address for intf 0""" defaultIP: default IP address for intf 0"""
self.name = name self.name = name
closeFds = False # speed vs. memory use 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 # 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 self.inNamespace = inNamespace
if self.inNamespace: if self.inNamespace:
cmd = [ 'netns' ] + cmd cmd = [ 'netns' ] + cmd
...@@ -143,20 +144,22 @@ def sendCmd( self, cmd ): ...@@ -143,20 +144,22 @@ def sendCmd( self, cmd ):
self.write( cmd + separator + ' echo -n "\\0177" \n' ) self.write( cmd + separator + ' echo -n "\\0177" \n' )
self.waiting = True 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 ): def monitor( self ):
"Monitor the output of a command, returning (done?, data)." "Monitor the output of a command, returning (done?, data)."
assert self.waiting assert self.waiting
self.waitReadable() self.waitReadable()
data = self.read( 1024 ) 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 self.waiting = False
return True, data[ :-1 ] return True, data[ :-1 ]
else: elif chr( 127 ) in data:
return False, 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 ): def waitOutput( self, verbose=False ):
"""Wait for a command to complete. """Wait for a command to complete.
...@@ -165,18 +168,12 @@ def waitOutput( self, verbose=False ): ...@@ -165,18 +168,12 @@ def waitOutput( self, verbose=False ):
the output, including trailing newline. the output, including trailing newline.
verbose: print output interactively""" verbose: print output interactively"""
log = info if verbose else debug log = info if verbose else debug
assert self.waiting
output = '' output = ''
while True: done = False
self.waitReadable() while not done:
data = self.read( 1024 ) done, data = self.monitor()
if len( data ) > 0 and data[ -1 ] == chr( 0177 ): output += data
output += data[ :-1 ] log( data )
log( output )
break
else:
output += data
self.waiting = False
return output return output
def cmd( self, cmd, verbose=False ): def cmd( self, cmd, verbose=False ):
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment