diff options
author | Shane Kearns <shane.kearns@accenture.com> | 2011-01-07 15:57:28 (GMT) |
---|---|---|
committer | Jason McDonald <jason.mcdonald@nokia.com> | 2011-01-11 09:54:14 (GMT) |
commit | 16e203e5de2aa984dadad2e4edd68d1c3446d9c1 (patch) | |
tree | ed88de0b963bfdb892133480d7b778452b71fbb8 | |
parent | 497cd0564b2471354b1ac86f00c5ba90845aa2e1 (diff) | |
download | Qt-16e203e5de2aa984dadad2e4edd68d1c3446d9c1.zip Qt-16e203e5de2aa984dadad2e4edd68d1c3446d9c1.tar.gz Qt-16e203e5de2aa984dadad2e4edd68d1c3446d9c1.tar.bz2 |
Fix handle leak in symbian QTimer implementation
The timer handle was only being closed when a timer was cancelled,
which resulted in a leak for one shot timers that have completed normally.
Instead the timer is now closed in a destructor (closing null handles is
safe, so it doesn't matter if the handle was never created - e.g. in the
case of a zero timer)
Also added a handle check before creating a timer to prevent a leak in
case the start function is called twice in the backend.
Task-number: QTBUG-16380
Reviewed-by: mread
(cherry picked from commit 2b1b617664bfc78f6e95e53dc0f9749bd1f2d27a)
-rw-r--r-- | src/corelib/kernel/qeventdispatcher_symbian.cpp | 6 | ||||
-rw-r--r-- | tests/auto/qtimer/tst_qtimer.cpp | 38 |
2 files changed, 42 insertions, 2 deletions
diff --git a/src/corelib/kernel/qeventdispatcher_symbian.cpp b/src/corelib/kernel/qeventdispatcher_symbian.cpp index bb9bd01..99c4087 100644 --- a/src/corelib/kernel/qeventdispatcher_symbian.cpp +++ b/src/corelib/kernel/qeventdispatcher_symbian.cpp @@ -217,13 +217,13 @@ QTimerActiveObject::QTimerActiveObject(QEventDispatcherSymbian *dispatcher, Symb QTimerActiveObject::~QTimerActiveObject() { Cancel(); + m_rTimer.Close(); //close of null handle is safe } void QTimerActiveObject::DoCancel() { if (m_timerInfo->interval > 0) { m_rTimer.Cancel(); - m_rTimer.Close(); } else { if (iStatus.Int() == KRequestPending) { TRequestStatus *status = &iStatus; @@ -302,7 +302,9 @@ void QTimerActiveObject::Start() CActiveScheduler::Add(this); m_timerInfo->msLeft = m_timerInfo->interval; if (m_timerInfo->interval > 0) { - m_rTimer.CreateLocal(); + if (!m_rTimer.Handle()) { + qt_symbian_throwIfError(m_rTimer.CreateLocal()); + } StartTimer(); } else { iStatus = KRequestPending; diff --git a/tests/auto/qtimer/tst_qtimer.cpp b/tests/auto/qtimer/tst_qtimer.cpp index 102308e..e964728 100644 --- a/tests/auto/qtimer/tst_qtimer.cpp +++ b/tests/auto/qtimer/tst_qtimer.cpp @@ -90,6 +90,9 @@ private slots: void QTBUG13633_dontBlockEvents(); void postedEventsShouldNotStarveTimers(); +#ifdef Q_OS_SYMBIAN + void handleLeaks(); +#endif }; class TimerHelper : public QObject @@ -750,5 +753,40 @@ void tst_QTimer::postedEventsShouldNotStarveTimers() QVERIFY(timerHelper.count > 5); } +#ifdef Q_OS_SYMBIAN +void tst_QTimer::handleLeaks() +{ + const int timercount = 5; + int processhandles_start; + int threadhandles_start; + RThread().HandleCount(processhandles_start, threadhandles_start); + { + TimerHelper timerHelper; + QList<QTimer*> timers; + for (int i=0;i<timercount;i++) { + QTimer* timer = new QTimer; + timers.append(timer); + connect(timer, SIGNAL(timeout()), &timerHelper, SLOT(timeout())); + timer->setSingleShot(true); + timer->start(i); //test both zero and normal timeouts + } + int processhandles_mid; + int threadhandles_mid; + RThread().HandleCount(processhandles_mid, threadhandles_mid); + qDebug() << threadhandles_mid - threadhandles_start << "new thread owned handles"; + QTest::qWait(100); + QCOMPARE(timerHelper.count, timercount); + qDeleteAll(timers); + } + int processhandles_end; + int threadhandles_end; + RThread().HandleCount(processhandles_end, threadhandles_end); + QCOMPARE(threadhandles_end, threadhandles_start); //RTimer::CreateLocal creates a thread owned handle + //Can not verify process handles because QObject::connect may create up to 2 mutexes + //from a QMutexPool (4 process owned handles with open C imp.) + //QCOMPARE(processhandles_end, processhandles_start); +} +#endif + QTEST_MAIN(tst_QTimer) #include "tst_qtimer.moc" |