In the latest PyQt 4.7 X11 snapshot (20091223), built against Qt 4.6.1 and
Python 2.6.2, I see an assertion failure on line 258 of
qpycore_pyqtproxy.cpp if, in Python, a slot is disconnected from a signal
while a signal is being processed. I built PyQt with the --debug option
passed to configure.py as I imagine that the assertion failure does not
occur in an optimized build. In this case, the signal is one that is defined
in and emitted by Python code, such as is shown below:
self.emit(QtCore.SIGNAL("pyClosed"), arg0)
Here, self is an object that derives from QtCore.QObject.
Is it no longer valid to disconnect a slot from its signal while the signal
is being processed? If I interpret a previous discussion on this list
correctly, then performing the slot disconnection step should not be
necessary to ensure that the Python object with the connected slots has its
reference count decremented if the Qt object to which it is connected is
destroyed. That discussion can be found here:
http://www.riverbankcomputing.com/pipermail/pyqt/2009-November/025069.html
Based on that, I wrote a test program that demonstrates that the Python
object's reference count does indeed decrease without the slot disconnection
step.
In case it is relevant, I have included the portion of the stack trace from
the signal emission in Python up to the assertion failure in PyQt. The full
stack in my test case is nearly 200 frames deep, and I suspect that no one
wants to see all of that.
#0 0x7fdf76315fb5 in raise () from /lib/libc.so.6
#1 0x7fdf76317bc3 in abort () from /lib/libc.so.6
#2 0x7fdf7328b3c9 in qt_message_output (msgType=QtFatalMsg,
buf=0x764e738 "ASSERT: \"(proxy_flags & PROXY_SLOT_INVOKED) == 0\" in
file qpycore_pyqtproxy.cpp, line 258") at global/qglobal.cpp:2226
#3 0x7fdf7328b5e4 in qt_message (msgType=QtFatalMsg,
msg=0x7fdf7344b748 "ASSERT: \"%s\" in file %s, line %d", ap=0x7fffc3ff3fc0)
at global/qglobal.cpp:2272
#4 0x7fdf7328b710 in qFatal (
msg=0x7fdf7344b748 "ASSERT: \"%s\" in file %s, line %d")
at global/qglobal.cpp:2455
#5 0x7fdf7328b985 in qt_assert (
assertion=0x7fdf703564d8 "(proxy_flags & PROXY_SLOT_INVOKED) == 0",
file=0x7fdf703564bd "qpycore_pyqtproxy.cpp", line=258)
at global/qglobal.cpp:1989
#6 0x7fdf70336c03 in ~PyQtProxy (this=0x8733470)
at qpycore_pyqtproxy.cpp:258
#7 0x7fdf70334c4c in pyqtBoundSignal_disconnect (self=0x3f60990,
args=0xbd67a90) at qpycore_pyqtboundsignal.cpp:495
#8 0x7fdf76fe9fbe in PyEval_EvalFrameEx (f=0x963e690,
throwflag=) at Python/ceval.c:3706
#9 0x7fdf76feb03d in PyEval_EvalFrameEx (f=0x8e48d40,
throwflag=) at Python/ceval.c:3792
#10 0x7fdf76febba9 in PyEval_EvalCodeEx (co=0x62abaf8,
globals=, locals=,
args=0x6ca1e30, argcount=2, kws=0x0, kwcount=0, defs=0x0, defcount=0,
closure=0x0) at Python/ceval.c:2968
#11 0x7fdf76f7204d in function_call (func=0x62bd1b8, arg=0x6ca1e18, kw=0x0)
at Objects/funcobject.c:524
#12 0x7fdf76f43ef8 in PyObject_Call (func=0x62bd1b8, arg=0x6ca1e18, kw=0x0)
at Objects/abstract.c:2492
#13 0x7fdf76f54690 in instancemethod_call (func=0x62bd1b8, arg=0x6ca1e18,
kw=0x0) at Objects/classobject.c:2579
#14 0x7fdf76f43ef8 in PyObject_Call (func=0x725ec80, arg=0xbe205d0, kw=0x0)
at Objects/abstract.c:2492
#15 0x7fdf76fe49c6 in PyEval_CallObjectWithKeywords (func=0x725ec80,
arg=0xbe205d0, kw=0x0) at Python/ceval.c:3575
#16 0x7fdf7061e9e2 in sip_api_invoke_slot (slot=0x7d42c70,
sigargs=0xbe205d0) at qtlib.c:191
#17 0x7fdf703369f3 in PyQtProxy::unislot (this=0x7d42c40,
qargs=0x7fffc3ff4ca0) at qpycore_pyqtproxy.cpp:411
#18 0x7fdf70336b50 in PyQtProxy::qt_metacall (this=0x7d42c40,
_c=QMetaObject::InvokeMetaMethod, _id=1, _a=0x7fffc3ff4ca0)
at qpycore_pyqtproxy.cpp:380
#19 0x7fdf733cc393 in QMetaObject::metacall (object=0x7d42c40,
cl=QMetaObject::InvokeMetaMethod, idx=5, argv=0x7fffc3ff4ca0)
at kernel/qmetaobject.cpp:237
#20 0x7fdf733e1813 in QMetaObject::activate (sender=0xba38450,
m=0x7fdf705a8840, local_signal_index=0, argv=0x7fffc3ff4ca0)
at kernel/qobject.cpp:3286
#21 0x7fdf703403cd in PyQtShortcircuitSignalProxy::pysignal (
this=0xba38450, _...@0x7fffc3ff4d10) at moc_qpycore_pyqtproxy.cpp:85
#22 0x7fdf7033d857 in PyQtShortcircuitSignalProxy::emit_signal (
this=0xba38450, ar...@0x7fffc3ff4d10) at qpycore_pyqtproxy.h:149
#23 0x7fdf7033c96c in emit_shortcircuit_signal (tx=0x87b3d50,
sig=0x7fdf4c1c0a64 "2pyClosed", sigargs=0xbe205d0)
at qpycore_sip_helpers.cpp:465
#24 0x7fdf7033d4a0 in qpycore_qobject_emit (qtx=0x87b3d50,
sig=0x7fdf4c1c0a64 "2pyClosed", sigargs=0xbe205d0)
at qpycore_sip_helpers.cpp:332
#25 0x7fdf7031bfee in meth_QObject_emit (sipSelf=0x9233af0,
sipArgs=0xc181d40)
at sip/QtCore/qobject.sip:467
#26 0x7fdf76fe9fbe in PyEval_EvalFrameEx (f=0xdc4b960,
throwflag=) at Python/ceval.c:3706
#27 0x