Handling of ConnectionLost exception in twisted
Question: I can not handle a ConnectionLost exception. Brief example of what I have.
First of all iIset up connection to jabber server and ping it. I use wokkel
library for that. Then I add errback to the method that is sending ping. In
the errback I handle the ConnectionLost error. After that, I close the
internet connection. But I can not see if that ConnectionLost is handled. I
close connection in my application and all exception handlers are invoked.

Ping goes well.

    
    
    [XmlStream,client] Ping to JID(u'jabber.ru') started at HivemindPingClientProtocol 
    [-] SEND: «iq to='jabber.ru' type='get' id='H_3'>/>»
    [XmlStream,client] RECV: "/><feature-not-implemented xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>"
    

Internet connection is closed

    
    
    [-] SEND: «iq to='jabber.ru' type='get' id='H_6'>/>»
    [-] SEND: «iq to='jabber.ru' type='get' id='H_7'>/>»
    

Handlers of ConnectionLost are not invoked. "Stream closed at
HivemindXMPPClient" is printed in StreamManager in _disconnected method

    
    
    [-] Protocol stopped
    [-] Protocol closed
    [-] Transport stopped
    [XmlStream,client] Stream closed at HivemindXMPPClient
    

All exception are handled after closing stream.

    
    
    [XmlStream,client] Failure [Failure instance: Traceback (failure with no frames): <class 'twisted.internet.error.ConnectionLost'>: Connection to the other side was lost in a non-clean fashion.
    [XmlStream,client] Failure [Failure instance: Traceback (failure with no frames): <class 'twisted.internet.error.ConnectionLost'>: Connection to the other side was lost in a non-clean fashion.] 
    [XmlStream,client] Connection lost with [Failure instance: Traceback (failure with no frames): <class 'twisted.internet.error.ConnectionDone'>: Connection was closed cleanly.] 
    [XmlStream,client] Stopping factory <hivemind.network.network_core.HivemindXmlStreamFactory object at 0xa2e904c>> 
    

Can anybody explain why errbacks are invoked after closing the stream?
Actually I want to implement a reconnect feature(I already use
ReconnectingFactory, but it does not react on ConnectionLost). Can someone
give me some example of reconnect implementation in twisted?

**Script example.** Run this script (make sure that ping work fine). Then
close your internet connection. When several ping has occured, you need to
terminate the script. As you can see, ConnectionLost errors are handled after
closing the connection.

    
    
    import sys
    from twisted.python import log
    from twisted.words.protocols import jabber
    from twisted.internet.error import ConnectionLost
    from wokkel.client import XMPPClient
    from wokkel.ping import PingClientProtocol
    from twisted.internet.task import LoopingCall
    
    JID = unicode('YOUR@JABBER.ID')
    PASSWORD = 'PASSWORD'
    INTERVAL = 3
    
    class SpecialPingClientProtocol(PingClientProtocol):
    
        def __init__(self, entity, interval):
            self.__entity = jabber.jid.internJID(entity)
            self.__interval = interval
            self.__pingLoop = None
    
        def _onError(self, failure):
            log.msg('Failure %s at %s' % (failure, self.__class__.__name__))
            error = failure.trap(jabber.error.StanzaError, ConnectionLost)
            if error == jabber.error.StanzaError:
                if failure.value.condition == 'feature-not-implemented':
                    return None
            elif error == ConnectionLost:
                # Do some beautiful things
                log.msg('Connection is lost. I want to reconnect NOW')
            return failure
    
        def _sendPing(self):
            defer = self.ping(self.__entity)
            defer.addErrback(self._onError)
    
        def stopPing(self):
            log.msg('Ping to %s stopped at %s' % (self.__entity, self.__class__.__name__))
            if self.__pingLoop is not None and self.__pingLoop.running:
                self.__pingLoop.stop()
                self.__pingLoop = None
    
        def startPing(self):
            log.msg('Ping to %s started at %s ' % (self.__entity, self.__class__.__name__))
            self.__pingLoop = LoopingCall(self._sendPing)
            self.__pingLoop.start(self.__interval, now = False)
    
    def main():
        log.startLogging(sys.stdout)
        transport = XMPPClient(jabber.jid.internJID(JID), PASSWORD)
        transport.logTraffic = True
        pinger = SpecialPingClientProtocol(JID, INTERVAL)
        pinger.setHandlerParent(transport)
        transport.startService()
        pinger.startPing()
        reactor.run()
    
    if __name__ == '__main__':
        from twisted.internet import reactor
        main()
    


Answer: Protocol has:

    
    
    clientConnectionFailed(self, connector, reason)
    clientConnectionLost(self, connector, reason)
    

you can override both and call PingClientProtocol.clientConnectionFailed and
PingClientProtocol.clientConnectionLost

assuming that PingClientProtocol inherit somehow from Protocol

