[PyQt] subtle bug in PyQt in combination with Python garbage collector

Erik Janssens Erik.Janssens at conceptive.be
Sat Aug 13 12:11:38 BST 2011


Hello Phil,

I believe to have found a subtle bug in PyQt in
combination with the Python garbage collector.

Here is what I think that happens :

- A QObject is constructed in one thread,
  and this QObject construction contains a cyclic
  dependency.

- this construction will not be deleted with
  reference counting, but only when the garbage
  collector is triggered

- now, if the garbage collector starts collecting
  in a different thread then the one that the 
  QObject was constructed in, the QObject gets
  destroyed in that different thread

- when a QObject is destroyed, it sends events to
  its parent object.  these events are then send in
  the wrong thread

- this leads to corruption and/or segmentation faults

To see this happening, please run the attached test 
case with a development build of Qt (because then,
you see the assertion failure).

I have observed this with :

- Qt 4.7.2
- PyQt 4.8.3
- sip 4.12.1

PySide suffers from the same behavior.

Thank you and best regards,

Erik


-------------- next part --------------
A non-text attachment was scrubbed...
Name: test_qt_bindings_garbage_collection.py
Type: text/x-python
Size: 2125 bytes
Desc: not available
URL: <http://www.riverbankcomputing.com/pipermail/pyqt/attachments/20110813/1a528014/attachment.py>
-------------- next part --------------
#0  0x00821416 in __kernel_vsyscall ()
#1  0x00e72941 in raise (sig=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:64
#2  0x00e75e42 in abort () at abort.c:92
#3  0x03c2c997 in qt_message_output (msgType=QtFatalMsg, buf=0x96ea6f8 "ASSERT failure in QCoreApplication::sendEvent: \"Cannot send events to objects owned by a different thread. Current thread 97870f0. Receiver '' (of type 'QWidget') was created in thread 9545fa8\", file "...) at global/qglobal.cpp:2282
#4  0x03c2cb8d in qt_message (msgType=QtFatalMsg, msg=0x3dd75f4 "ASSERT failure in %s: \"%s\", file %s, line %d", ap=0x2d22494 "\304[\343\003\360\245n\t\017[\343\003]\001") at global/qglobal.cpp:2328
#5  0x03c2cef3 in qFatal (msg=0x3dd75f4 "ASSERT failure in %s: \"%s\", file %s, line %d") at global/qglobal.cpp:2511
#6  0x03c2c53a in qt_assert_x (where=0x3e35bc4 "QCoreApplication::sendEvent", what=0x96ea5f0 "Cannot send events to objects owned by a different thread. Current thread 97870f0. Receiver '' (of type 'QWidget') was created in thread 9545fa8", file=0x3e35b0f "kernel/qcoreapplication.cpp", line=349) at global/qglobal.cpp:2035
#7  0x03d5542d in QCoreApplicationPrivate::checkReceiverThread (this=0x963e810, receiver=0x96dfe08) at kernel/qcoreapplication.cpp:349
#8  0x0514e96c in QApplication::notify (this=0x9548db8, receiver=0x96dfe08, e=0x2d22914) at kernel/qapplication.cpp:3754
#9  0x01635f02 in sipQApplication::notify (this=0x9548db8, a0=0x96dfe08, a1=0x2d22914) at sipQtGuiQApplication.cpp:317
#10 0x03d56178 in QCoreApplication::notifyInternal (this=0x9548db8, receiver=0x96dfe08, event=0x2d22914) at kernel/qcoreapplication.cpp:731
#11 0x05140e3d in QCoreApplication::sendEvent (receiver=0x96dfe08, event=0x2d22914) at ../../include/QtCore/../../src/corelib/kernel/qcoreapplication.h:215
#12 0x051a781e in QWidget::~QWidget (this=0x96dfe08, __in_chrg=<value optimized out>) at kernel/qwidget.cpp:1647
#13 0x01686d84 in sipQWidget::~sipQWidget (this=0x96dfe08, __in_chrg=<value optimized out>) at sipQtGuiQWidget.cpp:345
#14 0x03d6f226 in QObjectPrivate::deleteChildren (this=0x96ad5e8) at kernel/qobject.cpp:1955
#15 0x051a7788 in QWidget::~QWidget (this=0x96ad598, __in_chrg=<value optimized out>) at kernel/qwidget.cpp:1631
#16 0x01686d84 in sipQWidget::~sipQWidget (this=0x96ad598, __in_chrg=<value optimized out>) at sipQtGuiQWidget.cpp:345
#17 0x0169e40e in release_QWidget (sipCppV=0x96ad598, sipState=6) at sipQtGuiQWidget.cpp:9307
#18 0x0169e4ca in dealloc_QWidget (sipSelf=0xb70edf5c) at sipQtGuiQWidget.cpp:9325
#19 0x0094a30f in forgetObject (sw=0xb70edf5c) at siplib.c:10029
#20 0x00949b30 in sipWrapper_dealloc (self=0xb70edf5c) at siplib.c:9580
#21 0x00bd555a in subtype_dealloc (self=0xb70edf5c) at Objects/typeobject.c:1005
#22 0x00bb6734 in dict_dealloc (mp=0xb709746c) at Objects/dictobject.c:985
#23 0x009494d1 in sipSimpleWrapper_clear (self=0xb70f8d1c) at siplib.c:9150
#24 0x00949a4c in sipWrapper_clear (self=0xb70f8d1c) at siplib.c:9531
#25 0x00bd58f7 in subtype_clear (self=0xb70f8d1c) at Objects/typeobject.c:874
#26 0x00c56ad6 in delete_garbage (generation=<value optimized out>) at Modules/gcmodule.c:769
#27 collect (generation=<value optimized out>) at Modules/gcmodule.c:930
#28 0x00c574af in gc_collect (self=0x0, args=0xb76d402c, kws=0x0) at Modules/gcmodule.c:1067
#29 0x00bbabb8 in PyCFunction_Call (func=0xb70939ec, arg=0xb76d402c, kw=0x0) at Objects/methodobject.c:85
#30 0x00c1f901 in call_function (f=0x96e1dc4, throwflag=0) at Python/ceval.c:4012
#31 PyEval_EvalFrameEx (f=0x96e1dc4, throwflag=0) at Python/ceval.c:2665
#32 0x00c21270 in PyEval_EvalCodeEx (co=0xb711c218, globals=0xb71162d4, locals=0x0, args=0xb7101558, argcount=1, kws=0x0, kwcount=0, defs=0x0, defcount=0, closure=0xb711daa4) at Python/ceval.c:3252
#33 0x00ba0f17 in function_call (func=0xb70951b4, arg=0xb710154c, kw=0x0) at Objects/funcobject.c:526
#34 0x00b7159c in PyObject_Call (func=0xb70951b4, arg=0xb710154c, kw=0x0) at Objects/abstract.c:2529
#35 0x00b83484 in instancemethod_call (func=0xb70ef734, arg=0xb710154c, kw=0x0) at Objects/classobject.c:2578
#36 0x00b7159c in PyObject_Call (func=0xb70ef734, arg=0xb76d402c, kw=0x0) at Objects/abstract.c:2529
#37 0x00c19b94 in PyEval_CallObjectWithKeywords (func=0xb70ef734, arg=0xb76d402c, kw=0x0) at Python/ceval.c:3881
#38 0x0093efc0 in sip_api_call_method (isErr=0x0, method=0xb70ef734, fmt=0x721031b "") at siplib.c:1742
#39 0x0706df2a in sipVH_QtCore_11 (sipGILState=PyGILState_UNLOCKED, sipMethod=0xb70ef734) at sipQtCorecmodule.cpp:4376
#40 0x070b8664 in sipQThread::run (this=0x97870f0) at sipQtCoreQThread.cpp:165
#41 0x03c39fef in QThreadPrivate::start (arg=0x97870f0) at thread/qthread_unix.cpp:320
#42 0x00fc1cc9 in start_thread (arg=0x2d23b70) at pthread_create.c:304
#43 0x00f1869e in clone () at ../sysdeps/unix/sysv/linux/i386/clone.S:130



More information about the PyQt mailing list