summaryrefslogtreecommitdiffstats
path: root/src/corelib/kernel/qobject.cpp
diff options
context:
space:
mode:
authorJonathan Liu <net147@gmail.com>2014-09-18 19:54:46 +1000
committerJonathan Liu <net147@gmail.com>2014-09-23 00:47:34 +0200
commit7b7ad02681f2c28fb18d053618f6804e989b2f56 (patch)
treec79a8a04b4352f2ffac6b63a449d73c53787bd2e /src/corelib/kernel/qobject.cpp
parenta6316e6e744815c89b2d7bd7946e04549d183769 (diff)
Improve checking for event/socket notifiers and timers
Starting/stopping timers from another thread may result in errors that may not appear until hours, days or weeks after if a release build of Qt is used with the GLib/UNIX event dispatchers. Such errors may manifest as warnings such as "QObject::killTimer(): Error: timer id 7 is not valid for object 0x2a51b488 (), timer has not been killed" and application crashes (e.g. crashes in malloc, realloc and malloc_consolidate). Initial-patch-by: Eike Ziller <eike.ziller@digia.com> Task-number: QTBUG-40636 Change-Id: I2de50d50eb1fc7467fcebb9c73b74d2f85137933 Reviewed-by: Jocelyn Turcotte <jocelyn.turcotte@digia.com> Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Diffstat (limited to 'src/corelib/kernel/qobject.cpp')
-rw-r--r--src/corelib/kernel/qobject.cpp31
1 files changed, 21 insertions, 10 deletions
diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp
index 45bf4b62c5..bf814f36b9 100644
--- a/src/corelib/kernel/qobject.cpp
+++ b/src/corelib/kernel/qobject.cpp
@@ -225,13 +225,17 @@ QObjectPrivate::QObjectPrivate(int version)
QObjectPrivate::~QObjectPrivate()
{
if (extraData && !extraData->runningTimers.isEmpty()) {
- // unregister pending timers
- if (threadData->eventDispatcher.load())
- threadData->eventDispatcher.load()->unregisterTimers(q_ptr);
-
- // release the timer ids back to the pool
- for (int i = 0; i < extraData->runningTimers.size(); ++i)
- QAbstractEventDispatcherPrivate::releaseTimerId(extraData->runningTimers.at(i));
+ if (Q_LIKELY(threadData->thread == QThread::currentThread())) {
+ // unregister pending timers
+ if (threadData->eventDispatcher.load())
+ threadData->eventDispatcher.load()->unregisterTimers(q_ptr);
+
+ // release the timer ids back to the pool
+ for (int i = 0; i < extraData->runningTimers.size(); ++i)
+ QAbstractEventDispatcherPrivate::releaseTimerId(extraData->runningTimers.at(i));
+ } else {
+ qWarning("QObject::~QObject: Timers cannot be stopped from another thread");
+ }
}
if (postedEvents)
@@ -1612,15 +1616,18 @@ int QObject::startTimer(int interval, Qt::TimerType timerType)
{
Q_D(QObject);
- if (interval < 0) {
+ if (Q_UNLIKELY(interval < 0)) {
qWarning("QObject::startTimer: Timers cannot have negative intervals");
return 0;
}
-
- if (!d->threadData->eventDispatcher.load()) {
+ if (Q_UNLIKELY(!d->threadData->eventDispatcher.load())) {
qWarning("QObject::startTimer: Timers can only be used with threads started with QThread");
return 0;
}
+ if (Q_UNLIKELY(thread() != QThread::currentThread())) {
+ qWarning("QObject::startTimer: Timers cannot be started from another thread");
+ return 0;
+ }
int timerId = d->threadData->eventDispatcher.load()->registerTimer(interval, timerType, this);
if (!d->extraData)
d->extraData = new QObjectPrivate::ExtraData;
@@ -1640,6 +1647,10 @@ int QObject::startTimer(int interval, Qt::TimerType timerType)
void QObject::killTimer(int id)
{
Q_D(QObject);
+ if (Q_UNLIKELY(thread() != QThread::currentThread())) {
+ qWarning("QObject::killTimer: Timers cannot be stopped from another thread");
+ return;
+ }
if (id) {
int at = d->extraData ? d->extraData->runningTimers.indexOf(id) : -1;
if (at == -1) {