[Twisted-Python] How do I gracefully handle losing a connection?

fritz twisted-python at milkpotato.org
Wed Jan 3 14:54:39 EST 2007


Hello all,
I'm building off of the ssh client example in the excellent O'Reilly
book on Twisted by Abe Fettig but I've run into some problems and I'm
not sure how I should proceed.

Basically, I've implemented additional methods in order to handle
connection issues with the client. The goal being, exiting of the
program and printing out an error message detailing why the connection
failed:

class ClientCommandFactory(protocol.ClientFactory):

    ...

    def clientConnectionFailed(self, connector, reason):
        print reason.getErrorMessage()
        reactor.stop()

class CommandChannel(channel.SSHChannel):

    ...

    def closed(self):
        reactor.stop()

    def openFailed(self, reason):
        print reason.getErrorMessage()
        reactor.stop()

class ClientCommandTransport(transport.SSHClientTransport):

    ...

    def connectionFailed(self, reason):
        print reason.getErrorMessage()
        reactor.stop()

    def connectionLost(self, reason):
        print reason.getErrorMessage()
        reactor.stop()



The problem I'm currently facing is that. The connection properly ends
and the program exits when bad data is supplied on the command line but
when the program exits cleanly CommandChannel.closed() forces a call to
ClientCommandTransport.connectionLost() and we see an exception thrown
on a connection that I thought should end cleanly:

Connection to the other side was lost in a non-clean fashion: Connection
lost.
Traceback (most recent call last):
  File "/usr/lib/python2.3/site-packages/twisted/internet/posixbase.py",
line 226, in mainLoop
    self.runUntilCurrent()
  File "/usr/lib/python2.3/site-packages/twisted/internet/base.py", line
555, in runUntilCurrent
    call.func(*call.args, **call.kw)
  File "/usr/lib/python2.3/site-packages/twisted/internet/base.py", line
414, in _continueSystemEvent
    callable(*args, **kw)
  File "/usr/lib/python2.3/site-packages/twisted/internet/base.py", line
375, in disconnectAll
    failure.Failure(main.CONNECTION_LOST))
--- <exception caught here> ---
  File "/usr/lib/python2.3/site-packages/twisted/python/log.py", line
53, in callWithLogger
    return callWithContext({"system": lp}, func, *args, **kw)
  File "/usr/lib/python2.3/site-packages/twisted/python/log.py", line
38, in callWithContext
    return context.call({ILogContext: newCtx}, func, *args, **kw)
  File "/usr/lib/python2.3/site-packages/twisted/python/context.py",
line 59, in callWithContext
    return self.currentContext().callWithContext(ctx, func, *args, **kw)
  File "/usr/lib/python2.3/site-packages/twisted/python/context.py",
line 37, in callWithContext
    return func(*args,**kw)
  File "/usr/lib/python2.3/site-packages/twisted/internet/tcp.py", line
554, in connectionLost
    Connection.connectionLost(self, reason)
  File "/usr/lib/python2.3/site-packages/twisted/internet/tcp.py", line
402, in connectionLost
    protocol.connectionLost(reason)
  File "code/python/sshclient/sshclient.py", line 33, in connectionLost
    reactor.stop()
  File "/usr/lib/python2.3/site-packages/twisted/internet/base.py", line
342, in stop
    raise RuntimeError, "can't stop reactor that isn't running"
exceptions.RuntimeError: can't stop reactor that isn't running


If I remove reactor.stop() from ClientCommandTransport.connectionLost()
I then face the issue of some connection problems not being handled
correctly and the program will go idle on some bad connections.

So my question is, how can I fix my code to handle these exceptions and
all cases of bad connections and connections terminating abnormally?
Where should I implement connectionLost() and connectionFailed() and
how can I cleanly disconnect from the SSH server without seeing ugly
errors like the one above?

Thanks in advance,
Fritz





More information about the Twisted-Python mailing list