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

REG->5.14.2: Deadlock in conjunction with (cython's) nogil when calling to separate thread from QObject::event (Paint)

    XMLWordPrintable

Details

    • Bug
    • Resolution: Done
    • P1: Critical
    • None
    • 5.14.2
    • PySide
    • None
    • 270d2be98ad72e0cffb20339c3a42c8f81e3b8ec (pyside/pyside-setup/5.14)

    Description

      Between 5.14.1 and 5.14.2, a regression was introduced, causing a deadlock out of the box with one of our tools (https://github.com/gopro/gopro-lib-node.gl/).

      You'll need the following 3 files to reproduce the issue:

      1. qtbug.pyx:

      cdef class X:
      
          def nogil_noop(self):
              with nogil:
                  pass
      

      2. setup.py:

      from setuptools import setup
      from Cython.Build import cythonize
      
      setup(ext_modules = cythonize("qtbug.pyx"))
      

      3. runme.py:

      from PySide2 import QtCore, QtWidgets
      from PySide2.QtCore import QEvent
      
      import qtbug
      
      
      class _Thread(QtCore.QThread):
      
          def __init__(self):
              super().__init__()
              self._mutex = QtCore.QMutex()
              self._pyx = qtbug.X()
      
          def run(self):
              while True:
                  with QtCore.QMutexLocker(self._mutex):
                      self._pyx.nogil_noop()
      
          def draw(self):
              with QtCore.QMutexLocker(self._mutex):
                  pass
      
      
      class _Widget(QtWidgets.QWidget):
      
          def __init__(self):
              super().__init__()
              self._thread = _Thread()
              self._thread.start()
      
          def event(self, event):
              print(event)
              if event.type() == QEvent.Paint:
                  self._thread.draw()
              return super().event(event)
      
      
      if __name__ == '__main__':
          import sys
          app = QtWidgets.QApplication(sys.argv)
          window = _Widget()
          window.show()
          app.exec_()
      

      To reproduce:

      # Create and enter a Python virtualenv
      virtualenv venv
      . venv/bin/activate
      
      # Build the small binding
      pip install cython
      python setup.py build_ext --inplace
      
      # Install PySide and run the script
      pip install -U pyside2==5.14.2.1
      python runme.py
      

      If it doesn't deadlock right away, resizing the window will.

      To compare with a working version:

      pip install -U pyside2==5.14.1
      python runme.py
      

      Following is the backtrace with that test case:

      (gdb) bt
      #0  0x00007ffff7ec3f8d in syscall () from /usr/lib/libc.so.6
      #1  0x00007ffff5a8d6f5 in QBasicMutex::lockInternal() () from /home/ux/tmp/pyside-bug/venv/lib/python3.8/site-packages/PySide2/Qt/lib/libQt5Core.so.5
      #2  0x00007ffff5a8d746 in QMutex::lock() () from /home/ux/tmp/pyside-bug/venv/lib/python3.8/site-packages/PySide2/Qt/lib/libQt5Core.so.5
      #3  0x00007ffff65c7687 in Sbk_QMutexLocker_Init () from /home/ux/tmp/pyside-bug/venv/lib/python3.8/site-packages/PySide2/QtCore.abi3.so
      #4  0x00007ffff7b401aa in _PyObject_MakeTpCall () from /usr/lib/libpython3.8.so.1.0
      #5  0x00007ffff7bfdc51 in _PyEval_EvalFrameDefault () from /usr/lib/libpython3.8.so.1.0
      #6  0x00007ffff7beb1d6 in ?? () from /usr/lib/libpython3.8.so.1.0
      #7  0x00007ffff7bfd80a in _PyEval_EvalFrameDefault () from /usr/lib/libpython3.8.so.1.0
      #8  0x00007ffff7be98f4 in _PyEval_EvalCodeWithName () from /usr/lib/libpython3.8.so.1.0
      #9  0x00007ffff7beac7b in _PyFunction_Vectorcall () from /usr/lib/libpython3.8.so.1.0
      #10 0x00007ffff7beb4ab in ?? () from /usr/lib/libpython3.8.so.1.0
      #11 0x00007ffff7b463fd in PyObject_Call () from /usr/lib/libpython3.8.so.1.0
      #12 0x00007ffff2306bb2 in QWidgetWrapper::event(QEvent*) () from /home/ux/tmp/pyside-bug/venv/lib/python3.8/site-packages/PySide2/QtWidgets.abi3.so
      #13 0x00007ffff15e8b0c in QApplicationPrivate::notify_helper(QObject*, QEvent*) ()
         from /home/ux/tmp/pyside-bug/venv/lib/python3.8/site-packages/PySide2/Qt/lib/libQt5Widgets.so.5
      #14 0x00007ffff15efa90 in QApplication::notify(QObject*, QEvent*) () from /home/ux/tmp/pyside-bug/venv/lib/python3.8/site-packages/PySide2/Qt/lib/libQt5Widgets.so.5
      #15 0x00007ffff1e77565 in QApplicationWrapper::notify(QObject*, QEvent*) () from /home/ux/tmp/pyside-bug/venv/lib/python3.8/site-packages/PySide2/QtWidgets.abi3.so
      #16 0x00007ffff5c6fc48 in QCoreApplication::notifyInternal2(QObject*, QEvent*) ()
         from /home/ux/tmp/pyside-bug/venv/lib/python3.8/site-packages/PySide2/Qt/lib/libQt5Core.so.5
      #17 0x00007ffff16200c5 in QWidgetPrivate::sendPaintEvent(QRegion const&) ()
         from /home/ux/tmp/pyside-bug/venv/lib/python3.8/site-packages/PySide2/Qt/lib/libQt5Widgets.so.5
      #18 0x00007ffff1620bc7 in QWidgetPrivate::drawWidget(QPaintDevice*, QRegion const&, QPoint const&, QFlags<QWidgetPrivate::DrawWidgetFlag>, QPainter*, QWidgetRepaintManager*) () from /home/ux/tmp/pyside-bug/venv/lib/python3.8/site-packages/PySide2/Qt/lib/libQt5Widgets.so.5
      #19 0x00007ffff15f8f7f in QWidgetRepaintManager::paintAndFlush() () from /home/ux/tmp/pyside-bug/venv/lib/python3.8/site-packages/PySide2/Qt/lib/libQt5Widgets.so.5
      #20 0x00007ffff15f9648 in QWidgetRepaintManager::sync() () from /home/ux/tmp/pyside-bug/venv/lib/python3.8/site-packages/PySide2/Qt/lib/libQt5Widgets.so.5
      #21 0x00007ffff162174f in QWidgetPrivate::syncBackingStore() () from /home/ux/tmp/pyside-bug/venv/lib/python3.8/site-packages/PySide2/Qt/lib/libQt5Widgets.so.5
      #22 0x00007ffff16403d7 in QWidgetWindow::handleResizeEvent(QResizeEvent*) ()
         from /home/ux/tmp/pyside-bug/venv/lib/python3.8/site-packages/PySide2/Qt/lib/libQt5Widgets.so.5
      #23 0x00007ffff164391b in QWidgetWindow::event(QEvent*) () from /home/ux/tmp/pyside-bug/venv/lib/python3.8/site-packages/PySide2/Qt/lib/libQt5Widgets.so.5
      #24 0x00007ffff15e8b0c in QApplicationPrivate::notify_helper(QObject*, QEvent*) ()
         from /home/ux/tmp/pyside-bug/venv/lib/python3.8/site-packages/PySide2/Qt/lib/libQt5Widgets.so.5
      #25 0x00007ffff15efa90 in QApplication::notify(QObject*, QEvent*) () from /home/ux/tmp/pyside-bug/venv/lib/python3.8/site-packages/PySide2/Qt/lib/libQt5Widgets.so.5
      #26 0x00007ffff1e77565 in QApplicationWrapper::notify(QObject*, QEvent*) () from /home/ux/tmp/pyside-bug/venv/lib/python3.8/site-packages/PySide2/QtWidgets.abi3.so
      #27 0x00007ffff5c6fc48 in QCoreApplication::notifyInternal2(QObject*, QEvent*) ()
         from /home/ux/tmp/pyside-bug/venv/lib/python3.8/site-packages/PySide2/Qt/lib/libQt5Core.so.5
      #28 0x00007ffff0cd452c in QGuiApplicationPrivate::processGeometryChangeEvent(QWindowSystemInterfacePrivate::GeometryChangeEvent*) ()
         from /home/ux/tmp/pyside-bug/venv/lib/python3.8/site-packages/PySide2/Qt/lib/libQt5Gui.so.5
      #29 0x00007ffff0cd8d2d in QGuiApplicationPrivate::processWindowSystemEvent(QWindowSystemInterfacePrivate::WindowSystemEvent*) ()
         from /home/ux/tmp/pyside-bug/venv/lib/python3.8/site-packages/PySide2/Qt/lib/libQt5Gui.so.5
      #30 0x00007ffff0cb4f4b in QWindowSystemInterface::sendWindowSystemEvents(QFlags<QEventLoop::ProcessEventsFlag>) ()
         from /home/ux/tmp/pyside-bug/venv/lib/python3.8/site-packages/PySide2/Qt/lib/libQt5Gui.so.5
      #31 0x00007fffef9ac33a in xcbSourceDispatch(_GSource*, int (*)(void*), void*) ()
         from /home/ux/tmp/pyside-bug/venv/lib/python3.8/site-packages/PySide2/Qt/plugins/platforms/../../lib/libQt5XcbQpa.so.5
      #32 0x00007ffff2cf16be in g_main_context_dispatch () from /usr/lib/libglib-2.0.so.0
      #33 0x00007ffff2cf3531 in ?? () from /usr/lib/libglib-2.0.so.0
      #34 0x00007ffff2cf3571 in g_main_context_iteration () from /usr/lib/libglib-2.0.so.0
      #35 0x00007ffff5cc873c in QEventDispatcherGlib::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) ()
         from /home/ux/tmp/pyside-bug/venv/lib/python3.8/site-packages/PySide2/Qt/lib/libQt5Core.so.5
      #36 0x00007ffff5c6e662 in QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) ()
         from /home/ux/tmp/pyside-bug/venv/lib/python3.8/site-packages/PySide2/Qt/lib/libQt5Core.so.5
      #37 0x00007ffff5c77590 in QCoreApplication::exec() () from /home/ux/tmp/pyside-bug/venv/lib/python3.8/site-packages/PySide2/Qt/lib/libQt5Core.so.5
      #38 0x00007ffff1e75038 in Sbk_QApplicationFunc_exec_ () from /home/ux/tmp/pyside-bug/venv/lib/python3.8/site-packages/PySide2/QtWidgets.abi3.so
      #39 0x00007ffff7a8d587 in ?? () from /usr/lib/libpython3.8.so.1.0
      #40 0x00007ffff7bfd80a in _PyEval_EvalFrameDefault () from /usr/lib/libpython3.8.so.1.0
      #41 0x00007ffff7be98f4 in _PyEval_EvalCodeWithName () from /usr/lib/libpython3.8.so.1.0
      #42 0x00007ffff7c70d73 in PyEval_EvalCode () from /usr/lib/libpython3.8.so.1.0
      #43 0x00007ffff7c70dc8 in ?? () from /usr/lib/libpython3.8.so.1.0
      #44 0x00007ffff7c75063 in ?? () from /usr/lib/libpython3.8.so.1.0
      #45 0x00007ffff7b0fdf0 in PyRun_FileExFlags () from /usr/lib/libpython3.8.so.1.0
      #46 0x00007ffff7b19aa4 in PyRun_SimpleFileExFlags () from /usr/lib/libpython3.8.so.1.0
      #47 0x00007ffff7c8181e in Py_RunMain () from /usr/lib/libpython3.8.so.1.0
      #48 0x00007ffff7c81909 in Py_BytesMain () from /usr/lib/libpython3.8.so.1.0
      #49 0x00007ffff7df1023 in __libc_start_main () from /usr/lib/libc.so.6
      #50 0x000055555555505e in _start ()
      (gdb)
      

      Note the use of the with nogil in the Cython binding.

      Attachments

        No reviews matched the request. Check your Options in the drop-down menu of this sections header.

        Activity

          People

            crmaurei Cristian Maureira-Fredes
            ux U X
            Votes:
            0 Vote for this issue
            Watchers:
            5 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved:

              Gerrit Reviews

                There are no open Gerrit changes