[PyQt] segfault with multiple inheritance and QGraphicsItems

Zach Pincus zpincus at gmail.com
Wed May 1 16:34:52 BST 2019


Hello,

I've traced a segfault in PyQt5 to multiple inheritance with
QGraphicsItems. Below is a minimal example to reproduce this issue:

#######
from PyQt5 import Qt

class Mixin:
   pass

class MyItem(Mixin, Qt.QGraphicsRectItem):
   def itemChange(self, change, value):
       return value

myitem = MyItem()
rect = Qt.QGraphicsRectItem(parent=myitem) # segfault here
#######

If MyItem doesn't inherit from Mixin, there's no problem. (The order
of the superclasses doesn't matter, BTW.) If MyItem doesn't override
itemChange, there's again no problem. (It can override other methods
from QGraphicsItem just fine, as far as I can tell.) And if the parent
of rect on the last line is None, there's no problem.

This is tested with the latest PyQt5 from pip (5.12.1), but the issue
reproduces across many versions of PyQt5. It happens on macOS and
linux; I have not tested on windows. Below is an LLDB backtrace of the
segfault on a mac, and a GDB backtrace from a Ubuntu install.

Note also that the following works fine:
myitem = MyItem()
rect = Qt.QGraphicsRectItem(parent=None)
rect.setParentItem(myItem)

However, that workaround doesn't seem to apply to the larger Qt
application that I'm working on, from which this example is extracted.
In particular, the workaround creates some kind race condition that
freezes the application. I don't fully understand that race, but I
suspect it may well be related to the segfault here. So I'm hoping if
I can fix the segfault in this simple example, I can get my
application working properly.

And obviously in the full application, there's a good reason to need
to use a mixin class, even though it's just a placeholder here. (I'm
trying to make it possible to add a set of behaviors to an arbitrary
QGraphicsItem subclass, and inheritance of those behaviors via mixin
seems like the most straightforward way to do this.)

Any suggestions / workarounds would be welcome!

Thanks,
Zach



*** GDB backtrace on up-to-date Ubuntu ***

Program received signal SIGSEGV, Segmentation fault.
0x00007ffff5da743d in QObject::connect(QObject const*, char const*,
QObject const*, char const*, Qt::ConnectionType) ()
  from /usr/local/miniconda3/lib/python3.6/site-packages/PyQt5/Qt/lib/libQt5Core.so.5
(gdb) bt
#0  0x00007ffff5da743d in QObject::connect(QObject const*, char
const*, QObject const*, char const*, Qt::ConnectionType) ()
  from /usr/local/miniconda3/lib/python3.6/site-packages/PyQt5/Qt/lib/libQt5Core.so.5
#1  0x00007ffff64429dc in PyQtMonitor::monitor(QObject*) () from
/usr/local/miniconda3/lib/python3.6/site-packages/PyQt5/QtCore.so
#2  0x00007ffff2d27c45 in sipSimpleWrapper_init () from
/usr/local/miniconda3/lib/python3.6/site-packages/PyQt5/sip.so
#3  0x00005555556f0f57 in type_call () at
/tmp/build/80754af9/python_1540319457073/work/Objects/typeobject.c:915
#4  0x00005555556671de in PyObject_Call () at
/tmp/build/80754af9/python_1540319457073/work/Objects/abstract.c:2261
#5  0x00007ffff2d296b6 in sipWrapInstance () from
/usr/local/miniconda3/lib/python3.6/site-packages/PyQt5/sip.so
#6  0x00007ffff2d1cafb in sip_api_convert_from_type () from
/usr/local/miniconda3/lib/python3.6/site-packages/PyQt5/sip.so
#7  0x00007ffff643e10b in Chimera::toPyObject(void*) const () from
/usr/local/miniconda3/lib/python3.6/site-packages/PyQt5/QtCore.so
#8  0x00007ffff643d8e3 in Chimera::toPyObject(QVariant const&) const
() from /usr/local/miniconda3/lib/python3.6/site-packages/PyQt5/QtCore.so
#9  0x00007ffff643dba8 in Chimera::toAnyPyObject(QVariant const&) ()
from /usr/local/miniconda3/lib/python3.6/site-packages/PyQt5/QtCore.so
#10 0x00007ffff2d25aa9 in sip_api_convert_from_new_type () from
/usr/local/miniconda3/lib/python3.6/site-packages/PyQt5/sip.so
#11 0x00007ffff2d260e8 in buildObject () from
/usr/local/miniconda3/lib/python3.6/site-packages/PyQt5/sip.so
#12 0x00007ffff2d26a09 in call_method () from
/usr/local/miniconda3/lib/python3.6/site-packages/PyQt5/sip.so
#13 0x00007ffff2d26c0c in sip_api_call_method () from
/usr/local/miniconda3/lib/python3.6/site-packages/PyQt5/sip.so
#14 0x00007fffeb73d10c in sipVH_QtWidgets_154(PyGILState_STATE, void
(*)(_sipSimpleWrapper*, PyGILState_STATE), _sipSimpleWrapper*,
_object*, QGraphicsItem::GraphicsItemChange, QVariant const&) () from
/usr/local/miniconda3/lib/python3.6/site-packages/PyQt5/QtWidgets.so
#15 0x00007fffeb848ddc in
sipQGraphicsRectItem::itemChange(QGraphicsItem::GraphicsItemChange,
QVariant const&) ()
  from /usr/local/miniconda3/lib/python3.6/site-packages/PyQt5/QtWidgets.so
#16 0x00007fffeb0f3034 in
QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem*, QVariant
const*, QVariant const*) ()
  from /usr/local/miniconda3/lib/python3.6/site-packages/PyQt5/Qt/lib/libQt5Widgets.so.5
#17 0x00007fffeb0f3717 in QGraphicsItem::setParentItem(QGraphicsItem*) ()
  from /usr/local/miniconda3/lib/python3.6/site-packages/PyQt5/Qt/lib/libQt5Widgets.so.5
#18 0x00007fffeb0f3ca9 in
QAbstractGraphicsShapeItem::QAbstractGraphicsShapeItem(QAbstractGraphicsShapeItemPrivate&,
QGraphicsItem*) ()
  from /usr/local/miniconda3/lib/python3.6/site-packages/PyQt5/Qt/lib/libQt5Widgets.so.5
#19 0x00007fffeb0f40bd in
QGraphicsRectItem::QGraphicsRectItem(QGraphicsItem*) ()
  from /usr/local/miniconda3/lib/python3.6/site-packages/PyQt5/Qt/lib/libQt5Widgets.so.5
#20 0x00007fffeb752409 in
sipQGraphicsRectItem::sipQGraphicsRectItem(QGraphicsItem*) ()
  from /usr/local/miniconda3/lib/python3.6/site-packages/PyQt5/QtWidgets.so
#21 0x00007fffeb75270a in init_type_QGraphicsRectItem () from
/usr/local/miniconda3/lib/python3.6/site-packages/PyQt5/QtWidgets.so
#22 0x00007ffff2d27c94 in sipSimpleWrapper_init () from
/usr/local/miniconda3/lib/python3.6/site-packages/PyQt5/sip.so
#23 0x00005555556f0f57 in type_call () at
/tmp/build/80754af9/python_1540319457073/work/Objects/typeobject.c:915
#24 0x00005555556675bb in _PyObject_FastCallDict () at
/tmp/build/80754af9/python_1540319457073/work/Objects/abstract.c:2331
#25 0x00005555556eb2aa in _PyObject_FastCallKeywords () at
/tmp/build/80754af9/python_1540319457073/work/Objects/abstract.c:2496
#26 0x00005555556f0d6e in call_function () at
/tmp/build/80754af9/python_1540319457073/work/Python/ceval.c:4861
#27 0x00005555557144d8 in _PyEval_EvalFrameDefault () at
/tmp/build/80754af9/python_1540319457073/work/Python/ceval.c:3351
#28 0x00005555556ebad9 in _PyEval_EvalCodeWithName (qualname=0x0,
name=<optimized out>, closure=0x0, kwdefs=0x0, defcount=0, defs=0x0,
   kwstep=2, kwcount=<optimized out>, kwargs=0x0, kwnames=0x0,
argcount=0, args=0x0, locals=0x7ffff7f422d0, globals=0x7ffff7f422d0,
   _co=0x7ffff6ae25d0) at
/tmp/build/80754af9/python_1540319457073/work/Python/ceval.c:4166
#29 PyEval_EvalCodeEx () at
/tmp/build/80754af9/python_1540319457073/work/Python/ceval.c:4187
#30 0x00005555556ec87c in PyEval_EvalCode (co=co at entry=0x7ffff6ae25d0,
globals=globals at entry=0x7ffff7f422d0,
locals=locals at entry=0x7ffff7f422d0)
   at /tmp/build/80754af9/python_1540319457073/work/Python/ceval.c:731
#31 0x000055555576d074 in run_mod () at
/tmp/build/80754af9/python_1540319457073/work/Python/pythonrun.c:1025
#32 0x000055555576d471 in PyRun_FileExFlags () at
/tmp/build/80754af9/python_1540319457073/work/Python/pythonrun.c:978
#33 0x000055555576d673 in PyRun_SimpleFileExFlags () at
/tmp/build/80754af9/python_1540319457073/work/Python/pythonrun.c:419
#34 0x000055555576d77d in PyRun_AnyFileExFlags () at
/tmp/build/80754af9/python_1540319457073/work/Python/pythonrun.c:81
#35 0x00005555557711b0 in run_file (p_cf=0x7fffffffe8cc,
filename=0x5555558ac690 L"foo.py", fp=0x55555593c900)
   at /tmp/build/80754af9/python_1540319457073/work/Modules/main.c:340
#36 Py_Main () at
/tmp/build/80754af9/python_1540319457073/work/Modules/main.c:811
#37 0x0000555555638b4e in main () at
/tmp/build/80754af9/python_1540319457073/work/Programs/python.c:69
#38 0x00007ffff77e6b97 in __libc_start_main (main=0x555555638a60
<main>, argc=2, argv=0x7fffffffead8, init=<optimized out>,
   fini=<optimized out>, rtld_fini=<optimized out>,
stack_end=0x7fffffffeac8) at ../csu/libc-start.c:310
#39 0x000055555571a1a8 in _start () at ../sysdeps/x86_64/elf/start.S:103


*** LLDB backtrace on an up-to-date Mac ***

* thread #1, queue = 'com.apple.main-thread', stop reason =
EXC_BAD_ACCESS (code=EXC_I386_GPFLT)
 * frame #0: 0x0000000109908c41
QtRemoteObjects.so`sipSubClass_QRemoteObjectNode(void**) + 49
   frame #1: 0x00000001022ea61d sip.so`convertSubClass + 152
   frame #2: 0x00000001022ea4dd sip.so`sip_api_convert_from_type + 225
   frame #3: 0x0000000101b60ef8 QtCore.so`Chimera::toPyObject(void*) const + 760
   frame #4: 0x0000000101b60b92 QtCore.so`Chimera::toPyObject(QVariant
const&) const + 338
   frame #5: 0x0000000101b61139
QtCore.so`Chimera::toAnyPyObject(QVariant const&) + 217
   frame #6: 0x00000001022ecec8 sip.so`sip_api_convert_from_new_type + 160
   frame #7: 0x00000001022f0b8f sip.so`buildObject + 2598
   frame #8: 0x00000001022f0edc sip.so`call_method + 58
   frame #9: 0x00000001022ecc1c sip.so`sip_api_call_method + 136
   frame #10: 0x00000001078e2c3a
QtWidgets.so`sipQGraphicsRectItem::itemChange(QGraphicsItem::GraphicsItemChange,
QVariant const&) + 202
   frame #11: 0x000000010806e540
QtWidgets`QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem*,
QVariant const*, QVariant const*) + 1456
   frame #12: 0x0000000108071691
QtWidgets`QGraphicsItem::setParentItem(QGraphicsItem*) + 513
   frame #13: 0x0000000108081f2d
QtWidgets`QGraphicsRectItem::QGraphicsRectItem(QGraphicsItem*) + 541
   frame #14: 0x00000001078e3cbb
QtWidgets.so`init_type_QGraphicsRectItem(_sipSimpleWrapper*, _object*,
_object*, _object**, _object**, _object**) + 139
   frame #15: 0x00000001022eaaa9 sip.so`sipSimpleWrapper_init + 175
   frame #16: 0x00000001000b5af1 python`type_call + 241
   frame #17: 0x0000000100008ef1 python`_PyObject_FastCallDict + 177
   frame #18: 0x0000000100011137 python`_PyObject_FastCallKeywords + 327
   frame #19: 0x000000010015f718 python`call_function + 392
   frame #20: 0x000000010015d225 python`_PyEval_EvalFrameDefault + 47013
   frame #21: 0x00000001001508c9 python`_PyEval_EvalCodeWithName + 425
   frame #22: 0x00000001001a955c python`PyRun_FileExFlags + 252
   frame #23: 0x00000001001a8a34 python`PyRun_SimpleFileExFlags + 372
   frame #24: 0x00000001001cf7c6 python`Py_Main + 3734
   frame #25: 0x0000000100000f59 python`main + 313
   frame #26: 0x00007fff79e603d5 libdyld.dylib`start + 1
   frame #27: 0x00007fff79e603d5 libdyld.dylib`start + 1


More information about the PyQt mailing list