[PyQt] Segfault: QGraphicsView, cyclic references, and threads

Kovid Goyal kovid at kovidgoyal.net
Mon Mar 28 07:09:03 BST 2011


I'd guess it is the python cyclic garbage collector running in the worker thread and deleting QObjects in that thread causing all sorts of nastiness. 

Disable it with the gc module and see if that fixes your problem. If it does, then run the gc manually in the GUI thread only using a QTimer.

Kovid.

On Sun, Mar 27, 2011 at 10:29:38PM -0400, Luke Campagnola wrote:
> Greetings All-Knowing PyQters,
> I have a strange bug that's causing segmentation faults in my program. I
> have identified some of the key contributors to the bug and a workaround,
> but I would love for someone to explain what causes the crash so I can avoid
> similar problems in the future.
> 
> Here are the things required to cause the crash:
> 1) Repeatedly creating and deleting a GraphicsView and GraphicsItem
> 2) The each GraphicsItem has a reference to the GraphicsView it is shown in
> 3) Having a second thread running and actively working
> 
> Usually a segmentation fault will occur after roughly 10-1000 create/delete
> cycles. Taking away any of these components prevents the crash. The second
> thread does not have to be doing anything specific and does not even have to
> be a QThread; it just has to be doing _something_. If the Item has a weakref
> to its View, there is no crash (and this is a perfectly acceptable
> workaround).
> 
> I have attached a GDB backtrace and a short script demonstrating the bug.
> When I run the script on my system (Ubuntu 10.04, PyQt 4.7.2), about half of
> the time it causes a segfault, and the rest of the time it just freezes.
> I've also tested the script on WinXp with PyQt 4.8.3 and 4.5.4, with similar
> results. PySide does not have the bug, so I suspect it is not a Qt issue.
> 
> Any advice would be greatly appreciated!
> 
> Luke
> 
> 
> !DSPAM:3,4d8ff2b960459713818798!

> GNU gdb (GDB) 7.1-ubuntu
> Copyright (C) 2010 Free Software Foundation, Inc.
> License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
> This is free software: you are free to change and redistribute it.
> There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
> and "show warranty" for details.
> This GDB was configured as "i486-linux-gnu".
> For bug reporting instructions, please see:
> <http://www.gnu.org/software/gdb/bugs/>...
> Reading symbols from /usr/bin/python...Reading symbols from /usr/lib/debug/usr/bin/python2.6...done.
> done.
> (gdb) run bugtest.py
> Starting program: /usr/bin/python bugtest.py
> [Thread debugging using libthread_db enabled]
> .[New Thread 0xb7d34b70 (LWP 1238)]
> [New Thread 0xb6594b70 (LWP 1239)]
> ..
> Program received signal SIGSEGV, Segmentation fault.
> 0x007afe8b in ?? () from /usr/lib/libQtCore.so.4
> (gdb) backtrace
> #0  0x007afe8b in ?? () from /usr/lib/libQtCore.so.4
> #1  0x007c0bd8 in QObject::disconnect(QObject const*, char const*, QObject const*, char const*) () from /usr/lib/libQtCore.so.4
> #2  0x007c241f in QObjectCleanupHandler::remove(QObject*) () from /usr/lib/libQtCore.so.4
> #3  0x007c24e4 in QObjectCleanupHandler::objectDestroyed(QObject*) () from /usr/lib/libQtCore.so.4
> #4  0x0080ee5d in QObjectCleanupHandler::qt_metacall(QMetaObject::Call, int, void**) () from /usr/lib/libQtCore.so.4
> #5  0x007aec9a in QMetaObject::metacall(QObject*, QMetaObject::Call, int, void**) () from /usr/lib/libQtCore.so.4
> #6  0x007b9336 in QMetaCallEvent::placeMetaCall(QObject*) () from /usr/lib/libQtCore.so.4
> #7  0x007ba3fe in QObject::event(QEvent*) () from /usr/lib/libQtCore.so.4
> #8  0x011cc4dc in QApplicationPrivate::notify_helper(QObject*, QEvent*) () from /usr/lib/libQtGui.so.4
> #9  0x011d305e in QApplication::notify(QObject*, QEvent*) () from /usr/lib/libQtGui.so.4
> #10 0x00ead1d7 in sipQApplication::notify (this=0x83339f0, a0=0x843fd98, a1=0x844f6d8) at sipQtGuipart9.cpp:18539
> #11 0x007a9a3b in QCoreApplication::notifyInternal(QObject*, QEvent*) () from /usr/lib/libQtCore.so.4
> #12 0x007ac473 in QCoreApplicationPrivate::sendPostedEvents(QObject*, int, QThreadData*) () from /usr/lib/libQtCore.so.4
> #13 0x007ac5dd in QCoreApplication::sendPostedEvents(QObject*, int) () from /usr/lib/libQtCore.so.4
> #14 0x007d5adf in ?? () from /usr/lib/libQtCore.so.4
> #15 0x00a1e5e5 in g_main_context_dispatch () from /lib/libglib-2.0.so.0
> #16 0x00a222d8 in ?? () from /lib/libglib-2.0.so.0
> #17 0x00a224b8 in g_main_context_iteration () from /lib/libglib-2.0.so.0
> #18 0x007d55d5 in QEventDispatcherGlib::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) () from /usr/lib/libQtCore.so.4
> #19 0x0128c135 in ?? () from /usr/lib/libQtGui.so.4
> #20 0x007ac841 in QCoreApplication::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) () from /usr/lib/libQtCore.so.4
> #21 0x005663dd in meth_QCoreApplication_processEvents (sipArgs=(), sipKwds=0x0) at sipQtCorepart7.cpp:13371
> #22 0x080e0a21 in call_function (f=
>     Frame 0x841592c, for file bugtest.py, line 24, in test (c=246, w=<QGraphicsView at remote 0xb750bc2c>, s=<QGraphicsScene at remote 0xb7eb0f6c>, i=<QGraphicsRectItem(view=<...>) at remote 0xb750bc6c>), throwflag=0) at ../Python/ceval.c:3750
> #23 PyEval_EvalFrameEx (f=
>     Frame 0x841592c, for file bugtest.py, line 24, in test (c=246, w=<QGraphicsView at remote 0xb750bc2c>, s=<QGraphicsScene at remote 0xb7eb0f6c>, i=<QGraphicsRectItem(view=<...>) at remote 0xb750bc6c>), throwflag=0) at ../Python/ceval.c:2412
> #24 0x080e1bb0 in fast_function (f=Frame 0x829c6dc, for file bugtest.py, line 45, in <module> (), throwflag=0) at ../Python/ceval.c:3836
> #25 call_function (f=Frame 0x829c6dc, for file bugtest.py, line 45, in <module> (), throwflag=0) at ../Python/ceval.c:3771
> #26 PyEval_EvalFrameEx (f=Frame 0x829c6dc, for file bugtest.py, line 45, in <module> (), throwflag=0) at ../Python/ceval.c:2412
> #27 0x080e2807 in PyEval_EvalCodeEx (co=0xb7fdc5c0, globals=
>     {'weakref': <module at remote 0xb7fa4614>, 'QtGui': <module at remote 0xb7fa44f4>, 'thread': <module at remote 0xb7fa456c>, '__builtins__': <module at remote 0xb7fa4074>, '__file__': 'bugtest.py', 'doWork': <function at remote 0xb7eabd4c>, '__package__': None, 'sys': <module at remote 0xb7fa408c>, 'time': <module at remote 0xb7fa45fc>, 'test': <function at remote 0xb7eabd14>, '__name__': '__main__', 'app': <QApplication at remote 0xb7eb042c>, 'QtCore': <module at remote 0xb7fa46a4>, '__doc__': None}, locals=
>     {'weakref': <module at remote 0xb7fa4614>, 'QtGui': <module at remote 0xb7fa44f4>, 'thread': <module at remote 0xb7fa456c>, '__builtins__': <module at remote 0xb7fa4074>, '__file__': 'bugtest.py', 'doWork': <function at remote 0xb7eabd4c>, '__package__': None, 'sys': <module at remote 0xb7fa408c>, 'time': <module at remote 0xb7fa45fc>, 'test': <function at remote 0xb7eabd14>, '__name__': '__main__', 'app': <QApplication at remote 0xb7eb042c>, 'QtCore': <module at remote 0xb7fa46a4>, '__doc__': None}, args=0x0, argcount=0, kws=0x0, kwcount=0, defs=0x0, defcount=0, closure=0x0) at ../Python/ceval.c:3000
> #28 0x080e2907 in PyEval_EvalCode (co=0xb7fdc5c0, globals=
>     {'weakref': <module at remote 0xb7fa4614>, 'QtGui': <module at remote 0xb7fa44f4>, 'thread': <module at remote 0xb7fa456c>, '__builtins__': <module at remote 0xb7fa4074>, '__file__': 'bugtest.py', 'doWork': <function at remote 0xb7eabd4c>, '__package__': None, 'sys': <module at remote 0xb7fa408c>, 'time': <module at remote 0xb7fa45fc>, 'test': <function at remote 0xb7eabd14>, '__name__': '__main__', 'app': <QApplication at remote 0xb7eb042c>, 'QtCore': <module at remote 0xb7fa46a4>, '__doc__': None}, locals=
>     {'weakref': <module at remote 0xb7fa4614>, 'QtGui': <module at remote 0xb7fa44f4>, 'thread': <module at remote 0xb7fa456c>, '__builtins__': <module at remote 0xb7fa4074>, '__file__': 'bugtest.py', 'doWork': <function at remote 0xb7eabd4c>, '__package__': None, 'sys': <module at remote 0xb7fa408c>, 'time': <module at remote 0xb7fa45fc>, 'test': <function at remote 0xb7eabd14>, '__name__': '__main__', 'app': <QApplication at remote 0xb7eb042c>, 'QtCore': <module at remote 0xb7fa46a4>, '__doc__': None}) at ../Python/ceval.c:541
> #29 0x081005ad in run_mod (fp=0x82a1e78, filename=0xbffff5a8 "bugtest.py", start=257, globals=
>     {'weakref': <module at remote 0xb7fa4614>, 'QtGui': <module at remote 0xb7fa44f4>, 'thread': <module at remote 0xb7fa456c>, '__builtins__': <module at remote 0xb7fa4074>, '__file__': 'bugtest.py', 'doWork': <function at remote 0xb7eabd4c>, '__package__': None, 'sys': <module at remote 0xb7fa408c>, 'time': <module at remote 0xb7fa45fc>, 'test': <function at remote 0xb7eabd14>, '__name__': '__main__', 'app': <QApplication at remote 0xb7eb042c>, 'QtCore': <module at remote 0xb7fa46a4>, '__doc__': None}, locals=
>     {'weakref': <module at remote 0xb7fa4614>, 'QtGui': <module at remote 0xb7fa44f4>, 'thread': <module at remote 0xb7fa456c>, '__builtins__': <module at remote 0xb7fa4074>, '__file__': 'bugtest.py', 'doWork': <function at remote 0xb7eabd4c>, '__package__': None, 'sys': <module at remote 0xb7fa408c>, 'time': <module at remote 0xb7fa45fc>, 'test': <function at remote 0xb7eabd14>, '__name__': '__main__', 'app': <QApplication at remote 0xb7eb042c>, 'QtCore': <module at remote 0xb7fa46a4>, '__doc__': None}, closeit=1, flags=0xbffff32c) at ../Python/pythonrun.c:1339
> #30 PyRun_FileExFlags (fp=0x82a1e78, filename=0xbffff5a8 "bugtest.py", start=257, globals=
>     {'weakref': <module at remote 0xb7fa4614>, 'QtGui': <module at remote 0xb7fa44f4>, 'thread': <module at remote 0xb7fa456c>, '__builtins__': <module at remote 0xb7fa4074>, '__file__': 'bugtest.py', 'doWork': <function at remote 0xb7eabd4c>, '__package__': None, 'sys': <module at remote 0xb7fa408c>, 'time': <module at remote 0xb7fa45fc>, 'test': <function at remote 0xb7eabd14>, '__name__': '__main__', 'app': <QApplication at remote 0xb7eb042c>, 'QtCore': <module at remote 0xb7fa46a4>, '__doc__': None}, locals=
>     {'weakref': <module at remote 0xb7fa4614>, 'QtGui': <module at remote 0xb7fa44f4>, 'thread': <module at remote 0xb7fa456c>, '__builtins__': <module at remote 0xb7fa4074>, '__file__': 'bugtest.py', 'doWork': <function at remote 0xb7eabd4c>, '__package__': None, 'sys': <module at remote 0xb7fa408c>, 'time': <module at remote 0xb7fa45fc>, 'test': <function at remote 0xb7eabd14>, '__name__': '__main__', 'app': <QApplication at remote 0xb7eb042c>, 'QtCore': <module at remote 0xb7fa46a4>, '__doc__': None}, closeit=1, flags=0xbffff32c) at ../Python/pythonrun.c:1325
> #31 0x08100812 in PyRun_SimpleFileExFlags (fp=0x82a1e78, filename=0xbffff5a8 "bugtest.py", closeit=1, flags=0xbffff32c) at ../Python/pythonrun.c:935
> #32 0x0805de5c in Py_Main (argc=2, argv=0xbffff414) at ../Modules/main.c:572
> #33 0x0805d03b in main (argc=2, argv=0xbffff414) at ../Modules/python.c:23
> (gdb) quit

> # -*- coding: utf-8 -*-
> import sys, time, weakref
> #from PySide import QtCore, QtGui  ## bug is not present in PySide
> from PyQt4 import QtCore, QtGui
> 
> app = QtGui.QApplication([])
> 
> def test():
>     for c in range(5000):
>         if c%100 == 0:
>             sys.stdout.write('.')
>         sys.stdout.flush()
>         
>         ## Create a GraphicsView and an item linking back to it
>         w = QtGui.QGraphicsView()
>         s = QtGui.QGraphicsScene()
>         w.setScene(s)
>         i = QtGui.QGraphicsRectItem(0,0,1,1)
>         s.addItem(i)
>         
>         i.view = w          ## <-- this is crucial
>         #i.view = weakref.ref(w)
>         
>         app.processEvents()
>     print "OK"
>          
> 
> def doWork():
>     while True:
>         x = '.'.join(['%f'%i for i in range(100)])  ## some work for the thread to do
>         if time is None:  ## main thread has started cleaning up, bail out now
>             break
>         time.sleep(1e-3)
> 
> ## Another thread must be active (python threads and QThreads both work)
> #class Thread(QtCore.QThread):
>     #def run(self):
>         #doWork()
> #th = Thread()  
> #th.start()    
> 
> import thread
> thread.start_new_thread(doWork, ())
> 
> test()
> 
> 

> _______________________________________________
> PyQt mailing list    PyQt at riverbankcomputing.com
> http://www.riverbankcomputing.com/mailman/listinfo/pyqt
> 
> !DSPAM:3,4d8ff2b960459713818798!


-- 
_____________________________________

Dr. Kovid Goyal 
http://www.kovidgoyal.net
http://calibre-ebook.com
_____________________________________
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 198 bytes
Desc: not available
URL: <http://www.riverbankcomputing.com/pipermail/pyqt/attachments/20110328/115db4d3/attachment-0001.pgp>


More information about the PyQt mailing list