[PyQt] Crash with shortcircuit signals

Giovanni Bajo rasky at develer.com
Tue Jul 10 17:42:22 BST 2007


Hi Phil,

a little crasher:

==============================================
from PyQt4.QtCore import *

app = QCoreApplication([])
for i in range(300):
     print i
     w1 = QObject(None)
     w2 = QObject(None)
     print id(w1), id(w2)
     QObject.connect(w2, SIGNAL("CRASH"), w1, SIGNAL("CRASH"))
     w2.emit(SIGNAL("CRASH"))
==============================================

This snippet segfaults on both Linux and Windows with recent SIP/PyQt 
versions. The segfault is due to an infinite loop, that can be aborted 
before it smashes the stack with this patch:

Index: sip/QtCore/qobject.sip
===================================================================
--- sip/QtCore/qobject.sip (revision 13422)
+++ sip/QtCore/qobject.sip (working copy)
@@ -955,9 +955,15 @@
  // wrapped tuple of Python argument objects.
  void PyQtProxy::pysignal(const PyQt_PyObject &pyargs)
  {
+    static int recursion = 0;
+
      void *_a[] = {0, const_cast<void *>(reinterpret_cast<const void 
*>(&pyargs))};

+    recursion += 1;
+    if (recursion == 5)
+       abort();
      QMetaObject::activate(this, &staticMetaObject, 0, _a);
+    recursion -= 1;
  }


I *think* it's related to an instance's address being reused by Python 
before PyQt has stopped bookkeeping its existence. On my computer, this 
is the output:

0
9193416 9193488
1
9193560 9193416
2
9193488 9193560
[segfault]

As you can see, the instance address is reused by Python, and this 
somewhat triggers the infinite loop in dispatching the signal (the 
signal becomes connected to the same instance emitting it).
-- 
Giovanni Bajo



More information about the PyQt mailing list