diff options
author | Bradley T. Hughes <bradley.hughes@nokia.com> | 2010-08-09 11:27:31 (GMT) |
---|---|---|
committer | Bradley T. Hughes <bradley.hughes@nokia.com> | 2010-08-09 12:57:48 (GMT) |
commit | 3b9c811a658d45f6e84a98ac26a5d122b34254fc (patch) | |
tree | 19bc8553629812d947353b724a83a3ac7cf4a28f /tests/auto | |
parent | 163458f6363d32be453a186e02216f574f62dda3 (diff) | |
download | Qt-3b9c811a658d45f6e84a98ac26a5d122b34254fc.zip Qt-3b9c811a658d45f6e84a98ac26a5d122b34254fc.tar.gz Qt-3b9c811a658d45f6e84a98ac26a5d122b34254fc.tar.bz2 |
Fix invalid memory write during recursive timer activation
The handler for one timer recurses the event loop, and the handler for
another timer removes the first timer, returning from the recursion and
the handler for the first timer causes an invalid write (since the timer
info for the first timer has been deleted).
Fix this by keeping an active reference in QTimerInfo (instead of just a
bool inTimerEvent). If this is non-zero, the timer is currently being
delivered, so we prevent more delivery. When a timer is removed and it's
activateRef is set, we clear it so that the delivery code knows now to
write to memory that's already been freed.
A side effect of this change is that we no longer need to track the
currentTimerInfo "globally" anymore, it can be a normal local variable
in the QTimerInfoList::activateTimers() function.
Task-number: QT-3553
Reviewed-by: olivier
Reviewed-by: joao
Diffstat (limited to 'tests/auto')
-rw-r--r-- | tests/auto/qtimer/tst_qtimer.cpp | 44 |
1 files changed, 44 insertions, 0 deletions
diff --git a/tests/auto/qtimer/tst_qtimer.cpp b/tests/auto/qtimer/tst_qtimer.cpp index a0408ef..8d213ed 100644 --- a/tests/auto/qtimer/tst_qtimer.cpp +++ b/tests/auto/qtimer/tst_qtimer.cpp @@ -86,6 +86,7 @@ private slots: void timerIdPersistsAfterThreadExit(); void cancelLongTimer(); void singleShotStaticFunctionZeroTimeout(); + void recurseOnTimeoutAndStopTimer(); }; class TimerHelper : public QObject @@ -623,5 +624,48 @@ void tst_QTimer::singleShotStaticFunctionZeroTimeout() QCOMPARE(helper.count, 1); } +class RecursOnTimeoutAndStopTimerTimer : public QObject +{ + Q_OBJECT + +public: + QTimer *one; + QTimer *two; + +public slots: + void onetrigger() + { + QCoreApplication::processEvents(); + } + + void twotrigger() + { + one->stop(); + } +}; + +void tst_QTimer::recurseOnTimeoutAndStopTimer() +{ + QEventLoop eventLoop; + QTimer::singleShot(1000, &eventLoop, SLOT(quit())); + + RecursOnTimeoutAndStopTimerTimer t; + t.one = new QTimer(&t); + t.two = new QTimer(&t); + + QObject::connect(t.one, SIGNAL(timeout()), &t, SLOT(onetrigger())); + QObject::connect(t.two, SIGNAL(timeout()), &t, SLOT(twotrigger())); + + t.two->setSingleShot(true); + + t.one->start(); + t.two->start(); + + (void) eventLoop.exec(); + + QVERIFY(!t.one->isActive()); + QVERIFY(!t.two->isActive()); +} + QTEST_MAIN(tst_QTimer) #include "tst_qtimer.moc" |