diff options
-rw-r--r-- | src/corelib/kernel/qeventdispatcher_win.cpp | 10 | ||||
-rw-r--r-- | tests/auto/qtimer/tst_qtimer.cpp | 40 |
2 files changed, 45 insertions, 5 deletions
diff --git a/src/corelib/kernel/qeventdispatcher_win.cpp b/src/corelib/kernel/qeventdispatcher_win.cpp index b7934db..9c308a3 100644 --- a/src/corelib/kernel/qeventdispatcher_win.cpp +++ b/src/corelib/kernel/qeventdispatcher_win.cpp @@ -331,7 +331,7 @@ public: WinTimerVec timerVec; WinTimerDict timerDict; void registerTimer(WinTimerInfo *t); - void unregisterTimer(WinTimerInfo *t); + void unregisterTimer(WinTimerInfo *t, bool closingDown = false); void sendTimerEvent(int timerId); // socket notifiers @@ -557,10 +557,10 @@ void QEventDispatcherWin32Private::registerTimer(WinTimerInfo *t) qErrnoWarning("QEventDispatcherWin32::registerTimer: Failed to create a timer"); } -void QEventDispatcherWin32Private::unregisterTimer(WinTimerInfo *t) +void QEventDispatcherWin32Private::unregisterTimer(WinTimerInfo *t, bool closingDown) { // mark timer as unused - if (!QObjectPrivate::get(t->obj)->inThreadChangeEvent) + if (!QObjectPrivate::get(t->obj)->inThreadChangeEvent && !closingDown) QAbstractEventDispatcherPrivate::releaseTimerId(t->timerId); if (t->interval == 0) { @@ -1019,8 +1019,8 @@ void QEventDispatcherWin32::closingDown() unregisterSocketNotifier((*(d->sn_except.begin()))->obj); // clean up any timers - while (!d->timerDict.isEmpty()) - unregisterTimer((*(d->timerDict.begin()))->timerId); + for (int i = 0; i < d->timerVec.count(); ++i) + d->unregisterTimer(d->timerVec.at(i), true); } bool QEventDispatcherWin32::event(QEvent *e) diff --git a/tests/auto/qtimer/tst_qtimer.cpp b/tests/auto/qtimer/tst_qtimer.cpp index 57502c7..36fce76 100644 --- a/tests/auto/qtimer/tst_qtimer.cpp +++ b/tests/auto/qtimer/tst_qtimer.cpp @@ -87,6 +87,7 @@ private slots: void restartedTimerFiresTooSoon(); void timerFiresOnlyOncePerProcessEvents_data(); void timerFiresOnlyOncePerProcessEvents(); + void timerIdPersistsAfterThreadExit(); }; class TimerHelper : public QObject @@ -562,5 +563,44 @@ void tst_QTimer::timerFiresOnlyOncePerProcessEvents() QCOMPARE(longSlot.count, 1); } +class TimerIdPersistsAfterThreadExitThread : public QThread +{ +public: + QTimer *timer; + int timerId, returnValue; + + TimerIdPersistsAfterThreadExitThread() + : QThread(), timer(0), timerId(-1), returnValue(-1) + { } + ~TimerIdPersistsAfterThreadExitThread() + { + delete timer; + } + + void run() + { + QEventLoop eventLoop; + timer = new QTimer; + connect(timer, SIGNAL(timeout()), &eventLoop, SLOT(quit())); + timer->start(100); + timerId = timer->timerId(); + returnValue = eventLoop.exec(); + } +}; + +void tst_QTimer::timerIdPersistsAfterThreadExit() +{ + TimerIdPersistsAfterThreadExitThread thread; + thread.start(); + QVERIFY(thread.wait(30000)); + QCOMPARE(thread.returnValue, 0); + + // even though the thread has exited, and the event dispatcher destroyed, the timer is still + // "active", meaning the timer id should NOT be reused (i.e. the event dispatcher should not + // have unregistered it) + int timerId = thread.startTimer(100); + QVERIFY((timerId & 0xffffff) != (thread.timerId & 0xffffff)); +} + QTEST_MAIN(tst_QTimer) #include "tst_qtimer.moc" |