From a79d5b8d0856a8f6c4de56a8d982c84ea20905a6 Mon Sep 17 00:00:00 2001 From: Volker Hilsheimer Date: Sat, 22 Mar 2025 14:27:23 +0100 Subject: QObject::disconnect: warn if a wildcard call disconnects from destroyed Qt relies internally on connections to the destroyed() signal of application-objects, for example to clean up accessibility interface implementations or other data structures that would otherwise grow or hold danging pointers. The QObject::disconnect function is already documented to be potentially dangerous, as a wildcard call (with signal, receiver, and method defaulted to nullptr) will disconnect everything. However, what happpens to work in one Qt release might break things in another if we add code that relies on connections to destroyed(). To make users aware of the danger of a wildcard disconnect call, and to help with fixing the issues that might arise, emit a warning when a wildcard disconnect() breaks an existing connection to the sender's destroyed() signal. Do this while we hold the connection mutex, and only if all parameters to the disconnect() call are wildcarded. This happens very rarely, and should never happen in performance critical code. Fix the only test I found emitting this warning due to a wildcard disconnect (the drag'n'drop subsystem relies on the destroyed signal). Store the only relevant connection instead so that we can disconnect when done. Fixes: QTBUG-134610 Pick-to: 6.9 6.8 Change-Id: I9e6dcade0d5572345b71e3e8f06902bbea1ef89a Reviewed-by: Fabian Kosmale --- src/corelib/kernel/qobject.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'src/corelib/kernel/qobject.cpp') diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index a12efad25ab..62202178288 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -3759,6 +3759,14 @@ bool QMetaObjectPrivate::disconnect(const QObject *sender, QObjectPrivate::ConnectionDataPointer connections(scd); if (signal_index < 0) { + // wildcard disconnect - warn if this disconnects destroyed() + if (!receiver && method_index < 0 && sender->d_func()->isSignalConnected(0)) { + qWarning("QObject::disconnect: wildcard call disconnects from destroyed signal of" + " %s::%s", sender->metaObject()->className(), + sender->objectName().isEmpty() + ? "unnamed" + : sender->objectName().toLocal8Bit().data()); + } // remove from all connection lists for (int sig_index = -1; sig_index < scd->signalVectorCount(); ++sig_index) { if (disconnectHelper(connections.data(), sig_index, receiver, method_index, slot, senderMutex, disconnectType)) -- cgit v1.2.3