[Twisted-Python] ITransport.write after IProtocol.connectionLost -- no failure/exception?

exvito here ex.vitorino at gmail.com
Thu Dec 15 10:07:42 MST 2016


Dear all,

The subject says most of it. While diagnosing a behavior on a somewhat
large codebase, I found out something somewhat surprising -- see
subject -- which is replicated with the minimal code example below.

It is a LineReceiver client that:
1. Connects to 127.0.0.1:10000.
2. Sends a line of text.
3. Disconnects one second later.
4. Tries to send another line of text, one second after disconnection.

I expected step 4 to fail somehow, given that Twisted promptly
detected that the connection closed and IProtocol.connectionLost was
called, as documented. Nevertheless, it does not fail.

So the questions are:
a) Why does it not fail? I'm sure there is a good reason for that, as
most things do in Twisted.
b) Does a protocol implementation, like the one in the example, really
need to track connectionMade / connectionLost calls before going for
self.transport.write?
c) Can a protocol implementation, instead, depend on
self.transport.connected for which I found no documentation? (I
probably missed it, where is it?)

Thanks in advance for enlightening me. :-)
Regards,
--
exvito


# --[ cut here ]----------------------------------------------------

from twisted.internet import protocol, reactor, defer
from twisted.protocols import basic


class ClientAPI(basic.LineReceiver):

    def _log(self, msg):
        print('[connected=%r] %s' % (self.transport.connected, msg))

    def _send(self, line):
        self.sendLine(line)
        self._log('sent: %r' % (line,))

    def connectionMade(self):
        self._log('connection made')
        self._send('first line')
        reactor.callLater(1, lambda: self.transport.loseConnection())

    def connectionLost(self, reason):
        self._log('connection lost')
        reactor.callLater(1, self.postConnectionLostCall)

    def postConnectionLostCall(self):
        self._send('post conn lost call - SHOULD FAIL')


class ClientFactory(protocol.ClientFactory):

    protocol = ClientAPI

    def clientConnectionFailed(self, connector, reason):
        print 'connection failed -', reason
        reactor.stop()


if __name__ == '__main__':

    factory = ClientFactory()
    reactor.connectTCP('127.0.0.1', 10000, factory)
    reactor.run()



More information about the Twisted-Python mailing list