[PyQt] Re: Crash with shortcircuit signals

Giovanni Bajo rasky at develer.com
Mon Jul 16 13:46:26 BST 2007


On 7/16/2007 2:36 PM, Phil Thompson wrote:
> On Tuesday 10 July 2007 5:42 pm, Giovanni Bajo wrote:
>> 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).
> 
> This will be fixed in tonight's PyQt snapshot.
> 
> The proxy created to handle the signal was being incorrectly reused by a new 
> QObject created at the same address as the one the proxy was created for. 
> Because there is no event processing going on, the proxy was not getting 
> deleted - because it was waiting for a deleteLater() to be acted on.

Thanks! Don't you have a gift for the impatients? :)
-- 
Giovanni Bajo



More information about the PyQt mailing list