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

QStateMachine.postEvent causes a crash if the python event object isn't kept alive

    XMLWordPrintable

Details

    • Bug
    • Resolution: Fixed
    • P3: Somewhat important
    • 6.8.0, 6.7.3
    • 6.7.2
    • PySide
    • None
    • c0abb71b2 (dev), 2fda2cc5e (6.7), c743c4407 (6.7.3)

    Description

      Just writing something like

      class MyClass(QObject):
          def __init__(self, parent):
              self.machine = QStateMachine(self)
      ...
          @Slot()
          def some_handler(self):
              self.machine.postEvent(QEvent(QEvent.Type.User))
      

      will cause a hard crash shortly after the state machine finishes processing the event.

      If you keep the Python reference to the QEvent alive at least long enough for the machine to process it then the crash can be avoided, e.g. writing something like

          @Slot()
          def some_handler(self):
              self.last_event = QEvent(QEvent.Type.User)
              self.machine.postEvent(self.last_event)
      

      is sufficient to prevent the crash though I imagine it might not work if multiple calls to some_handler occurred during the same tick of the event loop.

      The root cause seems to be QStateMachine.postEvent() not taking ownership of the event object despite that appearing to be the correct behaviour per the documentation.

      I can demonstrate this by contrasting it with QCoreApplication.postEvent which has similar phrasing around ownership in the docs, e.g.

              e1 = QEvent(QEvent.Type.User)
              print(f"Created event 1, owned by python? {Shiboken.ownedByPython(e1)}")
              QCoreApplication.postEvent(self.machine, e1)
              print(f"Posted event 1, owned by python? {Shiboken.ownedByPython(e1)}")
      
              e2 = QEvent(QEvent.Type.User)
              print(f"Created event 2, owned by python? {Shiboken.ownedByPython(e2)}")
              self.machine.postEvent(e2)
              print(f"Posted event 2, owned by python? {Shiboken.ownedByPython(e2)}")
      

      Produces the output:

      Created event 1, owned by python? True
      Posted event 1, owned by python? False
      Created event 2, owned by python? True
      Posted event 2, owned by python? True
      

      I think the fix might be a change to the shiboken configuration files for QStateMachine but I wasn't able to get a local build of PySide6 working on my machine to test that theory.

      Attachments

        For Gerrit Dashboard: PYSIDE-2870
        # Subject Branch Project Status CR V

        Activity

          People

            kleint Friedemann Kleint
            duncan.mackintosh Duncan Mackintosh
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved:

              Gerrit Reviews

                There are no open Gerrit changes