[Twisted-Python] Q: PyQt and error handling in Deferreds

Andrew Bennetts andrew-twisted at puzzling.org
Tue Jun 24 05:47:13 EDT 2003


On Tue, Jun 24, 2003 at 01:20:53PM +0400, Egor Cheshkov wrote:
> Hello!
> 
> I'm writing client application using Twisted and PyQt. I want to handle 
> connection errors by showing the message box that describes it, so my errback  
> looks like this:
> 
>     def _ebSessionRequest(self, err):
>         QMessageBox.critical(self, "Warder", "Can't connect to server.")
>         self.setEnabled(1)
>         self.editAccesCode.setFocus()
> 
> It works nice but when the errback fired i get two tracebacks:

I've trimmed down the traceback to a few "interesting" lines:

> Traceback (most recent call last):
>   File "/usr/lib/python2.2/site-packages/twisted/internet/defer.py", line 215, 
> in errback
>     self._startRunCallbacks(fail, 1)
[...]
>   File "main.py", line 185, in _ebSessionRequest
>     QMessageBox.critical(self, "Warder", "Can't connect to server.")
> --- <exception caught here> ---
>   File "/usr/lib/python2.2/site-packages/twisted/internet/qtreactor.py", line 
> 74, in read
>     why = w.doRead()
[...]
>   File "/usr/lib/python2.2/site-packages/twisted/web/xmlrpc.py", line 209, in 
> clientConnectionLost
>     self.deferred.errback(reason)
[...]
>   File "/usr/lib/python2.2/site-packages/twisted/internet/defer.py", line 240, 
> in _startRunCallbacks
>     raise AlreadyCalledError()
> twisted.internet.defer.AlreadyCalledError:

And then the second traceback looks to be the same as the first.

> My question is: is it normal? How can I avoid such tracebacks?

It appears that the t.web.xmlrpc.QueryFactory.clientConnectionLost handler
is being called twice on the same connection, somehow.  I'm guessing that
creating a QMessageBox in the handler re-enters the qtreactor, but the
reactor isn't re-entrant, so it re-runs the same events.  Or something.

Try this:

    def _ebSessionRequest(self, err):
        reactor.callLater(0, QMessageBox.critical, self, "Warder", 
                          "Can't connect to server.")
        self.setEnabled(1)
        self.editAccesCode.setFocus()

Or something like it.  This is mostly guesswork though, so I could easily be
completely wrong about what the problem is.

On a related note: perhaps we need to make the reactors smarter about
accidental re-entrancy, so that weird stuff like this can't happen?

-Andrew.





More information about the Twisted-Python mailing list