Opened 8 years ago

Closed 8 years ago

#5485 defect closed duplicate (duplicate)

Canceling a pending TCP4ClientEndpoint connection leads to an AlreadyCalledError

Reported by: Paolo Milani Owned by:
Priority: normal Milestone:
Component: core Keywords: endpoints cancel
Cc: Branch:


It seems that if a tcp connection is hanging (e.g. because the destiantion host sends no reply), attempting to cancel it will lead to a spurious AlreadyCalledError.

Here is a small test case that triggers this bug:

from twisted.internet import reactor
from twisted.internet.protocol import Factory, Protocol
from twisted.internet.endpoints import TCP4ClientEndpoint
from twisted.internet import defer

class Greeter(Protocol):

class GreeterFactory(Factory):
    def buildProtocol(self, addr):
        return Greeter()

def gotProtocol(p):
    print "Got protocol"
def connectionFailed(f):
    print "Connection failed"

def timeout(d):
    print "Got timeout"
    if not d.called:

point = TCP4ClientEndpoint(reactor, "", 666)
d = point.connect(GreeterFactory())
reactor.callLater(10, timeout, d)

Notice I even test d.called before calling d.cancel(). does not respond on port 666, and after 10 seconds I get:

Got timeout
Connection failed
Unhandled Error
Traceback (most recent call last):
  File "", line 28, in <module>
  File "/usr/local/lib/python2.6/dist-packages/Twisted-11.1.0-py2.6-linux-x86_64.egg/twisted/internet/", line 1169, in run
  File "/usr/local/lib/python2.6/dist-packages/Twisted-11.1.0-py2.6-linux-x86_64.egg/twisted/internet/", line 1178, in mainLoop
--- <exception caught here> ---
  File "/usr/local/lib/python2.6/dist-packages/Twisted-11.1.0-py2.6-linux-x86_64.egg/twisted/internet/", line 800, in runUntilCurrent
    call.func(*call.args, **
  File "", line 21, in timeout
  File "/usr/local/lib/python2.6/dist-packages/Twisted-11.1.0-py2.6-linux-x86_64.egg/twisted/internet/", line 427, in cancel
  File "/usr/local/lib/python2.6/dist-packages/Twisted-11.1.0-py2.6-linux-x86_64.egg/twisted/internet/", line 261, in _canceller
  File "/usr/local/lib/python2.6/dist-packages/Twisted-11.1.0-py2.6-linux-x86_64.egg/twisted/internet/", line 391, in errback
  File "/usr/local/lib/python2.6/dist-packages/Twisted-11.1.0-py2.6-linux-x86_64.egg/twisted/internet/", line 451, in _startRunCallbacks
    raise AlreadyCalledError

Notice that the connection failed message is printed *after* the cancel() call.

Tested on:

twisted 11.1.0, python 2.6 on ubuntu 10.04 64 bit

twisted 11.1.0, python 2.7 on ubuntu 11.10 64 bit

Change History (2)

comment:1 Changed 8 years ago by Jean-Paul Calderone

Keywords: endpoints added; bug endpoint removed

Canceling the connection attempt leads to the Connector delivering connection failed notification to the factory, which the endpoint implementation intercepts. The endpoint implementation then tries to errback its result Deferred which is mid-cancelation at this point. Problems ensue.

The unit tests don't catch this because they use a fake Connector implementation that doesn't actually implement any Connector-like behavior at all.

comment:2 Changed 8 years ago by Jean-Paul Calderone

Resolution: duplicate
Status: newclosed

Duplicate of #4710.

Note: See TracTickets for help on using tickets.