Commit 71b4d4f1 is likely the source of the issue. It fixed a race on disconnection, but kept the call to disconnectNotify() (which is user code) inside the locked section. My analysis is that by construction the sender object can't be undergoing concurrent deletion anyway at this point. All call sites (QObject::disconnect or the signal-slot activations but before the slot is activated) imply that the user code that reached here cannot itself be racing the deletion.
There may be one race condition left: if the same signal was connected earlier to a slot via queued connection and that slot deletes the sender asynchronously. A synchronous deletion is handled by doActivate(), so the single-shot connection is never activated in the first place, but an asynchronous deletion could race past that check and delete the sender while QObjectPrivate::removeConnection is running. However, I'd call this a mistake in user code.
[ChangeLog][QtCore][QObject] Fixed a regression from 6.3 that caused QObject::isSignalConnected() to deadlock if called from inside disconnectNotify().
Fixes: QTBUG-106025 Pick-to: 5.15 6.2 6.3 6.4 Change-Id: Ic6547f8247454b47baa8fffd170fe0bdb62cfcaf Reviewed-by: Qt CI Bot email@example.com Reviewed-by: Lars Knoll firstname.lastname@example.org (cherry picked from commit 22d4c672)
Cherry-pick did not apply at all because the changed function does not exist in Qt5, instead manually picked the code change within
QObject::disconnect while omitting the added documentation which does not really fit here.