summaryrefslogtreecommitdiffstats
path: root/tests/auto/qtimer
diff options
context:
space:
mode:
authorBradley T. Hughes <bradley.hughes@nokia.com>2010-08-09 11:27:31 (GMT)
committerBradley T. Hughes <bradley.hughes@nokia.com>2010-08-09 12:57:48 (GMT)
commit3b9c811a658d45f6e84a98ac26a5d122b34254fc (patch)
tree19bc8553629812d947353b724a83a3ac7cf4a28f /tests/auto/qtimer
parent163458f6363d32be453a186e02216f574f62dda3 (diff)
downloadQt-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/qtimer')
-rw-r--r--tests/auto/qtimer/tst_qtimer.cpp44
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"