diff options
author | Giuseppe D'Angelo <giuseppe.dangelo@kdab.com> | 2012-12-16 23:06:45 +0100 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2012-12-17 19:50:31 +0100 |
commit | c4f433d581e2d609d2eaecc4e4b999a469950eb3 (patch) | |
tree | be310354c24429232f12412619cc01eb07a003f7 /tests/auto | |
parent | 058c029b1e035bc00447e846e888a7935c8f1902 (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.cpp | 56 |
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" |