summaryrefslogtreecommitdiffstats
path: root/tests/auto
diff options
context:
space:
mode:
authorGiuseppe D'Angelo <giuseppe.dangelo@kdab.com>2012-12-16 23:06:45 +0100
committerThe Qt Project <gerrit-noreply@qt-project.org>2012-12-17 19:50:31 +0100
commitc4f433d581e2d609d2eaecc4e4b999a469950eb3 (patch)
treebe310354c24429232f12412619cc01eb07a003f7 /tests/auto
parent058c029b1e035bc00447e846e888a7935c8f1902 (diff)
Reset the QMetaObject::Connection dptr when disconnect()ing
The QObjectPrivate::Connection refcount was not decreased when disconnect()ing, therefore it was kept alive by the owning QMetaObject::Connection object. This removes a leak in case the QMetaObject::Connection survives the sender object, after a successful disconnect(). Change-Id: Ie2ea59b269a0e589ae23c1457df7533be77c0797 Reviewed-by: Olivier Goffart <ogoffart@woboq.com>
Diffstat (limited to 'tests/auto')
-rw-r--r--tests/auto/corelib/kernel/qobject/tst_qobject.cpp56
1 files changed, 56 insertions, 0 deletions
diff --git a/tests/auto/corelib/kernel/qobject/tst_qobject.cpp b/tests/auto/corelib/kernel/qobject/tst_qobject.cpp
index 374975001f..76a97f89f4 100644
--- a/tests/auto/corelib/kernel/qobject/tst_qobject.cpp
+++ b/tests/auto/corelib/kernel/qobject/tst_qobject.cpp
@@ -141,6 +141,7 @@ private slots:
void returnValue2();
void connectVirtualSlots();
void connectFunctorArgDifference();
+ void disconnectDoesNotLeakFunctor();
};
class SenderObject : public QObject
@@ -5569,5 +5570,60 @@ void tst_QObject::connectFunctorArgDifference()
QVERIFY(true);
}
+static int countedStructObjectsCount = 0;
+struct CountedStruct
+{
+ CountedStruct() { ++countedStructObjectsCount; }
+ CountedStruct(const CountedStruct &) { ++countedStructObjectsCount; }
+ CountedStruct &operator=(const CountedStruct &) { return *this; }
+ ~CountedStruct() { --countedStructObjectsCount; }
+ void operator()() const {}
+};
+
+void tst_QObject::disconnectDoesNotLeakFunctor()
+{
+ QCOMPARE(countedStructObjectsCount, 0);
+ {
+ QMetaObject::Connection c;
+ {
+ CountedStruct s;
+ QCOMPARE(countedStructObjectsCount, 1);
+ QTimer timer;
+
+ c = connect(&timer, &QTimer::timeout, s);
+ QVERIFY(c);
+ QCOMPARE(countedStructObjectsCount, 2);
+ QVERIFY(QObject::disconnect(c));
+ // the connection list has been marked dirty, but not cleaned yet.
+ QCOMPARE(countedStructObjectsCount, 2);
+ }
+ // disconnect() dropped the reference that c had to the functor;
+ // the sender has been destroyed. Therefore, the QObjectPrivate::Connection
+ // refcount dropped to zero and destroyed the functor.
+ QCOMPARE(countedStructObjectsCount, 0);
+ }
+ QCOMPARE(countedStructObjectsCount, 0);
+ {
+ QMetaObject::Connection c1, c2;
+ {
+ CountedStruct s;
+ QCOMPARE(countedStructObjectsCount, 1);
+ QTimer timer;
+
+ c1 = connect(&timer, &QTimer::timeout, s);
+ QVERIFY(c1);
+ c2 = c1;
+ QVERIFY(c2);
+ QCOMPARE(countedStructObjectsCount, 2);
+ QVERIFY(QObject::disconnect(c1));
+ // the connection list has been marked dirty, but not cleaned yet.
+ QCOMPARE(countedStructObjectsCount, 2);
+ }
+ // c2 still holds a reference; c1 has been cleaned up
+ QCOMPARE(countedStructObjectsCount, 1);
+ }
+ QCOMPARE(countedStructObjectsCount, 0);
+}
+
QTEST_MAIN(tst_QObject)
#include "tst_qobject.moc"