Uploaded image for project: 'Qt for Python'
  1. Qt for Python
  2. PYSIDE-2022

segfault crash from QApplication::setFont() after deleting a temporary widget

    XMLWordPrintable

Details

    • Bug
    • Resolution: Invalid
    • Not Evaluated
    • None
    • 5.15.2
    • PySide
    • None
    • PySide/Qt 5.15.2
      Debian Stable (Bullseye) + KDE on a 4-core CPU
      Windows 10 on a 2-core VM
      Linux kernel 5.18.0-0.bpo.1-amd64
    • Linux/X11, Windows

    Description

      I have a QTreeView that displays thousands of items, each with variable height due to word-wrapped text. To accomplish this efficiently (i.e. avoid putting thousands of widgets in the event loop) the delegate creates temporary widgets to calculate item size in sizeHint() and draw in paint(). This works nicely.

      For performance when responding to rapid-fire events like mouse movement and window resizing, the most recently used temporary widgets are saved in an LRU cache. Old widgets are evicted from the cache and discarded when new ones are needed.

      The problem:

      When a user changes their system font, Qt crashes the process with a segmentation fault. The same thing happens if the app changes its own font with QApplication.setFont(). The crash is intermittent, but happens somewhat consistently on my system.

      The segfault does not occur if I disable the cache, causing temporary widgets to be discarded immediately after use instead of when new ones are created. (Of course, that also hurts event processing performance.)
      The segfault does not occur if I use QListView instead of QTreeView. (Of course, that is impractical for hierarchical items.)

      Crash backtrace:

      {{#0 0x00007f9d07eadf48 in QCoreApplication::notifyInternal2(QObject*, QEvent*)}}
       \{{ () from /lib/x86_64-linux-gnu/libQt5Core.so.5}}
       {{#1 0x00007f9d02b65a2e in QApplication::setFont(QFont const&, char const*) ()}}
       \{{ from /lib/x86_64-linux-gnu/libQt5Widgets.so.5}}
       {{#2 0x00007f9d033d682e in ?? ()}}
       \{{ from /usr/lib/python3/dist-packages/PySide2/QtWidgets.cpython-39-x86_64-linux-gnu.so}}
       {{#3 0x000000000053f350 in ?? ()}}
       {{#4 0x000000000051d89b in _PyObject_MakeTpCall ()}}
       {{#5 0x00000000005175ba in _PyEval_EvalFrameDefault ()}}
       {{#6 0x00000000005106ed in ?? ()}}
       {{#7 0x0000000000528d21 in _PyFunction_Vectorcall ()}}
       {{#8 0x000000000053bdb1 in ?? ()}}
       {{#9 0x00007f9d03817b63 in ?? ()}}
       \{{ from /usr/lib/python3/dist-packages/PySide2/QtWidgets.cpython-39-x86_64-linux-gnu.so}}
       {{#10 0x00007f9d02ba3e0f in QWidget::event(QEvent*) ()}}
       \{{ from /lib/x86_64-linux-gnu/libQt5Widgets.so.5}}
       {{#11 0x00007f9d02c4b42e in QFrame::event(QEvent*) ()}}
       \{{ from /lib/x86_64-linux-gnu/libQt5Widgets.so.5}}
       {{#12 0x00007f9d02b6315f in QApplicationPrivate::notify_helper(QObject*, QEvent*)}}
       \{{ () from /lib/x86_64-linux-gnu/libQt5Widgets.so.5}}
       {{#13 0x00007f9d02b6a56f in QApplication::notify(QObject*, QEvent*) ()}}
       \{{ from /lib/x86_64-linux-gnu/libQt5Widgets.so.5}}
       {{#14 0x00007f9d07eadfca in QCoreApplication::notifyInternal2(QObject*, QEvent*)}}
       \{{ () from /lib/x86_64-linux-gnu/libQt5Core.so.5}}
       {{#15 0x00007f9d02bbe398 in ?? () from /lib/x86_64-linux-gnu/libQt5Widgets.so.5}}
       {{#16 0x00007f9d02b6315f in QApplicationPrivate::notify_helper(QObject*, QEvent*)}}
       \{{ () from /lib/x86_64-linux-gnu/libQt5Widgets.so.5}}
       {{#17 0x00007f9d07eadfca in QCoreApplication::notifyInternal2(QObject*, QEvent*)}}
       \{{ () from /lib/x86_64-linux-gnu/libQt5Core.so.5}}
       {{#18 0x00007f9d043395a2 in QGuiApplicationPrivate::processKeyEvent(QWindowSystemInterfacePrivate::KeyEvent*) () from /lib/x86_64-linux-gnu/libQt5Gui.so.5}}
       {{#19 0x00007f9d0431364c in QWindowSystemInterface::sendWindowSystemEvents(QFlags<QEventLoop::ProcessEventsFlag>) () from /lib/x86_64-linux-gnu/libQt5Gui.so.5}}
       {{#20 0x00007f9d0290c7da in ?? () from /lib/x86_64-linux-gnu/libQt5XcbQpa.so.5}}
       {{#21 0x00007f9d06f39e6b in g_main_context_dispatch ()}}
       \{{ from /lib/x86_64-linux-gnu/libglib-2.0.so.0}}
       {{#22 0x00007f9d06f3a118 in ?? () from /lib/x86_64-linux-gnu/libglib-2.0.so.0}}
       {{#23 0x00007f9d06f3a1cf in g_main_context_iteration ()}}
       \{{ from /lib/x86_64-linux-gnu/libglib-2.0.so.0}}
       {{#24 0x00007f9d07f0551f in QEventDispatcherGlib::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) () from /lib/x86_64-linux-gnu/libQt5Core.so.5}}
       {{#25 0x00007f9d07eac98b in QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) () from /lib/x86_64-linux-gnu/libQt5Core.so.5}}
       {{#26 0x00007f9d07eb4c00 in QCoreApplication::exec() ()}}
       \{{ from /lib/x86_64-linux-gnu/libQt5Core.so.5}}
       {{#27 0x00007f9d033d7d95 in ?? ()}}
       \{{ from /usr/lib/python3/dist-packages/PySide2/QtWidgets.cpython-39-x86_64-linux-gnu.so}}
       {{#28 0x000000000052606e in ?? ()}}
       {{#29 0x0000000000516e76 in _PyEval_EvalFrameDefault ()}}
       {{#30 0x00000000005106ed in ?? ()}}
       {{#31 0x0000000000510497 in _PyEval_EvalCodeWithName ()}}
       {{#32 0x00000000005f5be3 in PyEval_EvalCode ()}}
       {{#33 0x0000000000619de7 in ?? ()}}
       {{#34 0x0000000000615610 in ?? ()}}
       {{#35 0x0000000000619d79 in ?? ()}}
       {{#36 0x0000000000619816 in PyRun_SimpleFileExFlags ()}}
       {{#37 0x000000000060d4e3 in Py_RunMain ()}}
       {{#38 0x00000000005ea6e9 in Py_BytesMain ()}}
       {{#39 0x00007f9d091cdd0a in __libc_start_main ()}}
       \{{ from /lib/x86_64-linux-gnu/libc.so.6}}
       {{#40 0x00000000005ea5ea in _start ()}}
      

      I don't have easy access to debug symbols, but gdb shows a 0 in the RDI register, which (if I understand amd64 calling conventions correctly) suggests that Qt called notifyInternal2() with a null pointer as its QObject* argument.

      I will attach a program that reproduces the crash with PySide 5.15.2 on KDE Plasma, Xfce, and Windows. Run the program, and hold the space bar until it crashes. It often crashes immediately for me, but I sometimes have to hold the space bar for 5-30 seconds. Running with different -style command line options may influence the likelihood of a crash.

      I have not been able to reproduce it with PySide 6.2.4 on Windows.

      Attachments

        1. pyside2022_log.txt
          2 kB
        2. pyside2022_stack.txt
          41 kB
        3. pyside2022.py
          4 kB
        4. test_segfault.py
          3 kB
        No reviews matched the request. Check your Options in the drop-down menu of this sections header.

        Activity

          People

            crmaurei Cristian Maureira-Fredes
            hforest H Forest
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved:

              Gerrit Reviews

                There are no open Gerrit changes