[Twisted-Python] Re-entrancy policy for the reactor

Glyph Lefkowitz glyph at twistedmatrix.com
Wed Jul 27 15:10:21 MDT 2011


On Jul 24, 2011, at 10:51 PM, Itamar Turner-Trauring wrote:

> I'm going to merge #5063 next time I have a few minutes when I'm more
> awake, which will mean my yak stack[1] is empty and I can go back to
> working on abortConnection(). As explained in
> http://twistedmatrix.com/trac/ticket/78,  abortConnection() is like
> loseConnection(), except it doesn't wait until buffers are written out,
> it closes the connection immediately. The question is, how immediately?
> 
> My current implementation, a bit like one of the half-close code paths,
> ends up calling connectionLost directly. That means you can have a call
> stack that looks like this:
> 
> MyProtocol.dataReceived
> TCPConnection.abortConnection
> ...
> MyProtocol.connectionLost
> 
> This can lead to re-entrancy bugs. I am tempted to suggest a policy of
> No Reactor Reentrancy, but that is currently violated by one of the TCP
> half-close code paths, and producers if I'm not mistaken.
> 
> Some options:
> 
> (a) Leave abortConnection() reentrant.
> (b) Make abortConnection() non-reentrant, don't change any current APIs.
> (c) Make all reactor APIs non-reentrant.
> 
> (Since there's a ticket for documenting the reentrancy policy, you will
> notice I've added another yak to my stack. I'll finish #78 someday!)
> 
> Thoughts?

My main thought here is that protocol reentrancy is bad, and nobody really expects it even if they think it should be fine.

However, I do believe it would be best (easier to test, in particular) to immediately call connectionLost within doRead (or doWrite) after dataReceived exits, rather than callLater(0)-ing it or otherwise placing it into a global call queue.

-glyph



More information about the Twisted-Python mailing list