[PyKDE] Re: Threading problem with PyQt4 and Macosx

Matt Newell newellm at blur.com
Fri Feb 23 22:34:28 GMT 2007


On Friday 23 February 2007 12:52, Matt Newell wrote:
> On Friday 23 February 2007 12:38, Michael Guntsche wrote:
> > On Feb 23, 2007, at 20:43, Matt Newell wrote:
>
> ...
>
> > Hello Matt,
> >
> > Can you try and change the connect to a QueuedConnection? It looks
> > like it is using a "DirectConnection" now.
> > I was sure I tried that before, but back then I was using events and
> > not signals.
>
> It's already (correctly) using a queued connection to send the signal.
> I've already tracked it down further and eliminated one of the deadlock
> code paths by putting a /ReleaseGIL/ annotation on QLabel::setText.  There
> is another deadlock though happening in the connect call which i'm tracking
> down now.
>
> > I tried it on my computer, but although the "connect" returns True I
> > do not get the emitted signal in my main thread.
> > I do not understand why.
>
> Hmm, i'm not sure why that would happen.
>


So here's the deal.  In order to avoid deadlocks we must avoid running any Qt 
code that will require a lock while the GIL is locked.  This is because we 
can't avoid the opposite, which is acquiring the GIL while Qt is holding a 
lock( For example Qt holds a lock while copying signal data for queued 
connections, and we have to run python code for that. )  To avoid a deadlock 
we must avoid one or the other.

This means that any Qt calls that do a connect, or create/destroy any qobjects 
must first release the GIL.  There may be other code paths in Qt that require 
the same care.

Try testing with this patch, it eliminates all deadlocks for me.

Index: sip/QtGui/qlabel.sip
===================================================================
--- sip/QtGui/qlabel.sip        (revision 4129)
+++ sip/QtGui/qlabel.sip        (working copy)
@@ -84,7 +84,7 @@
     void setNum(int);
     void setPicture(const QPicture &);
     void setPixmap(const QPixmap &);
-    void setText(const QString &);
+    void setText(const QString &) /ReleaseGIL/;

 signals:
 %If (Qt_4_2_0 -)
Index: sip/QtCore/qobject.sip
===================================================================
--- sip/QtCore/qobject.sip      (revision 4129)
+++ sip/QtCore/qobject.sip      (working copy)
@@ -838,9 +838,11 @@
     mutex.unlock();

     // Detect when the transmitter is destroyed.
-    if (tx)
+    if (tx) {
+        Py_BEGIN_ALLOW_THREADS
         connect(reinterpret_cast<QObject *>(tx), SIGNAL(destroyed(QObject 
*)), SLOT(deleteLater()));
-
+        Py_END_ALLOW_THREADS
+    }
     qtx = tx;
 }


Matt




More information about the PyQt mailing list