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

Inheritance causes slots to use global receiver connections

    XMLWordPrintable

Details

    • Bug
    • Resolution: Fixed
    • P3: Somewhat important
    • 6.6.0, 6.5.3
    • 6.3.2, 6.5.3
    • PySide
    • None
    • Windows 10 and Linux 6.4.7
      PySide 6.3.2 and 6.5.2 and 716b9c6435ee5de5de2cc229551624201807f3f6
    • Linux/X11, Windows
    • f048d13b4 (dev), 7b83f501c (dev), 9ef8a2ee4 (6.5), fa61e6bf4 (6.5), a8f7ee753 (dev), d3d4973ef (6.6), 9d3ee797a (6.5)

    Description

      Running the attached "testslots.py" results in the following output:

      6.3.2
      OBJECT A::unnamed
        SIGNALS OUT
              signal: sig()
                --> A::unnamed slotA()
        SIGNALS IN
                <-- A::unnamed slotA()
      OBJECT B::unnamed
        SIGNALS OUT
              signal: destroyed(QObject*)
                --> __GlobalReceiver__::unnamed __receiverDestroyed__(QObject*)
              signal: sig()
                --> __GlobalReceiver__::unnamed slotA2a0eb197bc02a0e8fc64d0()
        SIGNALS IN
              <None> 

      When A (the base class) is used by itself, the slots connect properly. However, when B (the subclass) is used, despite nothing being overridden, the slots all connect using the global receiver.

      The root cause of this appears to be the getReceiver (https://code.qt.io/cgit/pyside/pyside-setup.git/tree/sources/pyside6/libpyside/qobjectconnect.cpp?h=6.5#n111) function. On line 111, there is a check which is meant to check if the slot is a C++ slot overridden in Python. But since the meta object in use is the meta object of the subclasses, the check treats superclass Python slots like C++ slots, and decides that they override themselves. (for the attached code, methodOffset() returns 7, slotIndex is 6 and PyMethod_Check(callback) returns true)

      The reason I noticed this was a due to a "Internal C++ object (...) already deleted" error in our codebase. I've attached a file (crash.py) that can reproduce this error, which seems to some how create the perfect timing to get this error. It only causes the error on Windows, and does seem rather contrived, but it is a simplified version of what we had in our codebase and if we hit it by accident there must be other cases as well. To reproduce:

      • Start the script
      • Move the window to another monitor (in my case my monitors have different DPIs, not sure if that matters)
      • Click open
      • Then close the window that opens

      The output for me is:

      PySide6.QtCore.QSizeF(160.000000, 160.000000)
      Traceback (most recent call last):
        File "C:\Users\matthew.joyce\Repos\iscat_gui\crash.py", line 23, in _onSceneChange
          print(self.size())
      RuntimeError: Internal C++ object (CalibrationGraph) already deleted.
      Bye 

      The slot inconsistency happens on both Linux and Windows, with multiple PySide versions.

      Attachments

        1. crash.py
          2 kB
        2. testslots.py
          0.4 kB
        3. pyside2418.zip
          3 kB
        4. pyside2418_diag.diff
          2 kB
        5. pyside2418_log.txt
          2 kB

        Issue Links

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

          Activity

            People

              kleint Friedemann Kleint
              matsjoyce-refeyn Matthew Joyce
              Votes:
              0 Vote for this issue
              Watchers:
              4 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved: