Reputation: 251
I have written the following piece of code to handle a lost connection in twisted :
class Foo(LineReceiver):
def connectionLost(self, reason):
if reason.type != ConnectionLost:
reactor.stop()
def terminate(self):
self.transport.loseConnection()
The terminate
method is called by some input/output protocol.
I had to test reason.type
in the connectionLost
method to avoid an error
'can't stop reactor that isn' running' when I interrupt my program with Ctrl-C instead
of calling the terminate
method.
This code works but I wonder if there is a more elegant way of managing the end of a connection in twisted ? Thanks !
Upvotes: 3
Views: 2730
Reputation: 31860
The problem you're facing is that control+C is invoking an already-installed signal handler that stops the reactor. The reactor, while stopping, invokes your connectionLost
method, because shutting down the reactor automatically closes all connections. In turn, your protocol tries to stop the reactor - only to find it's already been stopped!
A simple (but not entirely correct) way to avoid this condition is to look at the running
attribute on the reactor before stopping it, like so:
def connectionLost(self, reason):
if reactor.running:
reactor.stop()
(Note also that you probably shouldn't check the exception type that way; you might want to use Failure.check
instead, if you actually care about the type of the reason, but in most cases you shouldn't care about the type of the reason; a broken connection is just a broken connection, unless you are trying to ascertain something very specific attributes of its brokenness, like for example whether the termination should cause an SSL session termination.)
If you want to be more thorough about checking for this, you will need to monitor the reactor's state via a "before", "shutdown"
system event trigger, or use the twisted.internet.task.react
API introduced in Twisted 12.3.
Upvotes: 4