Protect better against timer ID replacement

Timer IDs have been reused since Qt 4.5 or thereabouts, so just checking
if the timer ID is in the timer dictionary is an incorrect check: our
timer may have been deleted and replaced by another with the same ID.

Instead of deleting the WinTimerInfo object, let's just mark it as
unregistered by setting timerId to -1 and cooperate in deleting at the
appropriate places. Since unregisterTimer skips deleting if inTimerEvent
is true, the appropriate places are everywhere that set inTimerEvent to
true.

Change-Id: I057e93314e41372ae7a5ff93c467767c8a6d92ea
Reviewed-by: Friedemann Kleint <Friedemann.Kleint@qt.io>
Reviewed-by: Oliver Wolff <oliver.wolff@qt.io>
Reviewed-by: Joerg Bornemann <joerg.bornemann@qt.io>
This commit is contained in:
Thiago Macieira 2017-03-15 18:58:27 -07:00
parent 1b73d13975
commit cdaea16964

View File

@ -406,7 +406,9 @@ void QEventDispatcherWin32Private::unregisterTimer(WinTimerInfo *t)
} else if (internalHwnd) {
KillTimer(internalHwnd, t->timerId);
}
delete t;
t->timerId = -1;
if (!t->inTimerEvent)
delete t;
}
void QEventDispatcherWin32Private::sendTimerEvent(int timerId)
@ -423,8 +425,9 @@ void QEventDispatcherWin32Private::sendTimerEvent(int timerId)
QCoreApplication::sendEvent(t->obj, &e);
// timer could have been removed
t = timerDict.value(timerId);
if (t) {
if (t->timerId == -1) {
delete t;
} else {
t->inTimerEvent = false;
}
}
@ -1012,8 +1015,10 @@ bool QEventDispatcherWin32::event(QEvent *e)
QTimerEvent te(zte->timerId());
QCoreApplication::sendEvent(t->obj, &te);
t = d->timerDict.value(zte->timerId());
if (t) {
// timer could have been removed
if (t->timerId == -1) {
delete t;
} else {
if (t->interval == 0 && t->inTimerEvent) {
// post the next zero timer event as long as the timer was not restarted
QCoreApplication::postEvent(this, new QZeroTimerEvent(zte->timerId()));