You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Can't connect and disconnect Python callables to signals indefinitely #362
This is because for each source object which has signals connected to callables, a receiver object is generated (class PythonQtSignalReceiver) by PythonQt, and each time a callable is connected to a signal of this object, a virtual slot is generated on this receiver, which gets its own, consecutive slot ID. Slot IDs seem to be internally restricted to 16bit (effectively 15bit) by the connection record used by Qt. So after slot ID 32767 connects stop working.
It seems we need to reuse unused slot IDs after 32767. I would propose to start again with the initial start ID and increase it until a free ID is found.
There is a small risk that the reused slot IDs lead to the wrong callable being called in certain circumstances. For this to happen, the following things need to happen:
A signal "A" of an object is connected to a callable: An receiver object is created as a child of the sender object.
The QObject::destroyed signal is connected to a callable: This leads to the receiver being reparented, since otherwise this signal might not be received before the receiver is deleted (special life-time code is employed in this case).
The sender object is moved to another thread. The sender and its receiver object now belong to different threads.
The sender object emits signal "A". Because the connection type is Qt::AutoConnection, a QMetaCallEvent is put into the event queue of the receiver's thread.
Signal "A" is disconnected from the callable.
An undeterminate number of connects and disconnects to callables happen on the sender.
A signal from the sender object is connected to a different callable, which coincidentally gets the same slot ID as the previous receiver slot (since it is free now)
Events are processed on the receiver's thread: The QMetaCallEvent is passed to the receiver object, and the slot ID matches that of the new receiver slot: In this case the wrong callable is called.
An easy remedy to prevent this case would be to use Qt::DirectConnection instead of Qt::AutoConnection when connecting to callables. Callables would always be called on the thread that emits the signal, which probably is what users would expect anway. But we probably need to think somewhat more about thread-safety.
I decided to use a different approach and create a separate receiver object for each connect to a callable. This way no slot IDs are reused. This also allows to set the instance object of a method as parent if it is derived from QObject; this way the target thread for the AutoConnection should have the expected value (which was not the case previously).
Activity
Create a separate receiver object for each signal/callable connect
Create a separate receiver object for each signal/callable connect
usiems commentedon Sep 2, 2026
I decided to use a different approach and create a separate receiver object for each connect to a callable. This way no slot IDs are reused. This also allows to set the instance object of a method as parent if it is derived from QObject; this way the target thread for the AutoConnection should have the expected value (which was not the case previously).