[PyQt] Signals arriving after proxy slots deleted

Phil Thompson phil at riverbankcomputing.com
Sat Apr 14 15:14:28 BST 2012


On Wed, 11 Apr 2012 13:48:15 +0100, Andrew Suffield
<asuffield at suffields.me.uk> wrote:
> I've been having grief with a class of problems that looks like this
> valgrind error:
> 
> ==28760== Invalid write of size 4
> ==28760==    at 0x6C26DED: PyQtProxy::unislot(void**) (in
> /usr/lib/python2.7/dist-packages/PyQt4/QtCore.so)
> ==28760==    by 0x6C26EC1: PyQtProxy::qt_metacall(QMetaObject::Call,
int,
> void**) (in /usr/lib/python2.7/dist-packages/PyQt4/QtCore.so)
> ==28760==    by 0x7083DF8: QMetaObject::activate(QObject*, QMetaObject
> const*, int, void**) (in /usr/lib/x86_64-linux-gnu/libQtCore.so.4.8.0)
> ==28760==    by 0xCD7D945: QNetworkReplyImplPrivate::finished() (in
> /usr/lib/x86_64-linux-gnu/libQtNetwork.so.4.8.0)
> ==28760==    by 0xCDF3C64:
> QNetworkAccessHttpBackend::qt_static_metacall(QObject*,
QMetaObject::Call,
> int, void**) (in /usr/lib/x86_64-linux-gnu/libQtNetwork.so.4.8.0)
> ==28760==    by 0x7088DB5: QObject::event(QEvent*) (in
> /usr/lib/x86_64-linux-gnu/libQtCore.so.4.8.0)
> ==28760==    by 0x8F14EC3: QApplicationPrivate::notify_helper(QObject*,
> QEvent*) (in /usr/lib/x86_64-linux-gnu/libQtGui.so.4.8.0)
> ==28760==    by 0x8F19D42: QApplication::notify(QObject*, QEvent*) (in
> /usr/lib/x86_64-linux-gnu/libQtGui.so.4.8.0)
> ==28760==    by 0x8900CB8: sipQApplication::notify(QObject*, QEvent*)
(in
> /usr/lib/python2.7/dist-packages/PyQt4/QtGui.so)
> ==28760==    by 0x706F80B: QCoreApplication::notifyInternal(QObject*,
> QEvent*) (in /usr/lib/x86_64-linux-gnu/libQtCore.so.4.8.0)
> ==28760==    by 0x70735D9:
> QCoreApplicationPrivate::sendPostedEvents(QObject*, int, QThreadData*)
(in
> /usr/lib/x86_64-linux-gnu/libQtCore.so.4.8.0)
> ==28760==    by 0x709E962: postEventSourceDispatch(_GSource*, int
> (*)(void*), void*) (in /usr/lib/x86_64-linux-gnu/libQtCore.so.4.8.0)
> ==28760==  Address 0xed62f14 is 20 bytes inside a block of size 120
free'd
> ==28760==    at 0x402773C: operator delete(void*) (in
> /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
> ==28760==    by 0x6C276E8: PyQtProxy::deleteSlotProxies(void*, char
> const*) (in /usr/lib/python2.7/dist-packages/PyQt4/QtCore.so)
> ==28760==    by 0x6C24B20: pyqtBoundSignal_disconnect (in
> /usr/lib/python2.7/dist-packages/PyQt4/QtCore.so)
> ==28760==    by 0x4B9588: PyEval_EvalFrameEx (ceval.c:4021)
> 
> What's happened here is that a cross-thread connection from a
> QNetworkReply.finished signal to some python code has been
> .disconnect()ed, and then an event arrives from the thread where the
> network stuff is happening.
> 
> Unfortunately, it seems that .disconnect() in pyqt is also a delete of
> the receiving proxy object, which leads to memory corruption when the
> signal magic happens.
> 
> I'm working around the issue in the short term by not using
> disconnect, and making sure my QObjects don't get gced before the
> event loop's had time to drain (by keeping references to them lying
> around), but this is rather suboptimal in terms of code noise. What
> I'd like is a safe way to use disconnect, but I don't see how - is
> there actually a pyqt bug in here?

Once the C++ disconnect() has completed then it shouldn't matter if the
proxy is still around or not. Has the disconnect() actually succeeded?

Phil


More information about the PyQt mailing list