Ticket #3057 defect new
Opened 5 years ago
Insults ServerProtocol throws exception when characters arrive after terminalProtocol is deleted on logout / disconnect
| Reported by: | pwarner | Owned by: | |
|---|---|---|---|
| Priority: | normal | Milestone: | |
| Component: | conch | Keywords: | insults |
| Cc: | Branch: | ||
| Author: | Launchpad Bug: |
Description
I have a terminal protocol built on top of RecvLine on top of insults ServerProtocol. When a test script sends and extra exit, so 'exit\nexit\n' we some times get this in one chunk into insults.ServerProtocol.dataReceived (data='exit\nexit\n')
The problem is that RecvLine takes the first 'exit\n' and our protocol initiates tear down of the SSH connection. Once the exit request propagates down, eventually insults.ServerProtocol.connectionLost is called and we set self.terminalProtocol to None. The problem is we are still in the middle of processing things in insults.ServerProtocol.dataReceived, specifically we have another 'exit\n' left in this case, but it doesn't matter what is there, we end up calling self.terminalProtocol.keystrokeReceived, except self.terminalProtocol is now None, so we throw an exception.
I think a fix may be to just wrap the call in a try / except, but another option would be to feed back the fact that the processed characters caused the terminalProtocol to be cleared. I am not sure of the best fix, I understand my use of this stuff, but not the general use so well.
The exception I get is:
Traceback (most recent call last):
File "/usr/lib/python2.5/site-packages/twisted/python/context.py", line 59, in callWithContext
return self.currentContext().callWithContext(ctx, func, *args, **kw)
File "/usr/lib/python2.5/site-packages/twisted/python/context.py", line 37, in callWithContext
return func(*args,**kw)
File "/usr/lib/python2.5/site-packages/twisted/conch/ssh/service.py", line 42, in packetReceived
f(packet)
File "/usr/lib/python2.5/site-packages/twisted/conch/ssh/connection.py", line 139, in ssh_CHANNEL_DATA
log.callWithLogger(channel, channel.dataReceived, data)
--- <exception caught here> ---
File "/usr/lib/python2.5/site-packages/twisted/python/log.py", line 48, in callWithLogger
return callWithContext({"system": lp}, func, *args, **kw)
File "/usr/lib/python2.5/site-packages/twisted/python/log.py", line 33, in callWithContext
return context.call({ILogContext: newCtx}, func, *args, **kw)
File "/usr/lib/python2.5/site-packages/twisted/python/context.py", line 59, in callWithContext
return self.currentContext().callWithContext(ctx, func, *args, **kw)
File "/usr/lib/python2.5/site-packages/twisted/python/context.py", line 37, in callWithContext
return func(*args,**kw)
File "/usr/lib/python2.5/site-packages/twisted/conch/ssh/session.py", line 107, in dataReceived
self.client.transport.write(data)
File "/usr/lib/python2.5/site-packages/twisted/conch/ssh/session.py", line 156, in write
self.proto.dataReceived(data)
File "/usr/lib/python2.5/site-packages/twisted/conch/insults/insults.py", line 421, in dataReceived
self.terminalProtocol.keystrokeReceived(ch, None)
exceptions.AttributeError: 'NoneType' object has no attribute 'keystrokeReceived'
And the path we took that ended up setting self.terminalProtocol to None was:
/app/protocolSession.py(287)do_exit()
-> self.terminal.loseConnection()
/usr/lib/python2.5/site-packages/twisted/conch/insults/insults.py(759)loseConnection()
-> self.transport.loseConnection()
/usr/lib/python2.5/site-packages/twisted/conch/ssh/session.py(211)loseConnection()
-> self.session.loseConnection()
/usr/lib/python2.5/site-packages/twisted/conch/ssh/session.py(131)loseConnection()
-> self.client.transport.loseConnection()
/usr/lib/python2.5/site-packages/twisted/conch/ssh/session.py(162)loseConnection()
-> self.proto.connectionLost(protocol.connectionDone)
/usr/lib/python2.5/site-packages/twisted/conch/insults/insults.py(768)connectionLost()->None
