summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/corelib/kernel/qeventloop.cpp5
-rw-r--r--src/corelib/thread/qthread_unix.cpp5
-rw-r--r--src/corelib/thread/qthread_win.cpp5
-rw-r--r--tests/auto/qthread/tst_qthread.cpp16
4 files changed, 29 insertions, 2 deletions
diff --git a/src/corelib/kernel/qeventloop.cpp b/src/corelib/kernel/qeventloop.cpp
index e78f86a..d213b0e 100644
--- a/src/corelib/kernel/qeventloop.cpp
+++ b/src/corelib/kernel/qeventloop.cpp
@@ -175,6 +175,8 @@ bool QEventLoop::processEvents(ProcessEventsFlags flags)
int QEventLoop::exec(ProcessEventsFlags flags)
{
Q_D(QEventLoop);
+ //we need to protect from race condition with QThread::exit
+ QMutexLocker locker(&static_cast<QThreadPrivate *>(QObjectPrivate::get(d->threadData->thread))->mutex);
if (d->threadData->quitNow)
return -1;
@@ -186,6 +188,7 @@ int QEventLoop::exec(ProcessEventsFlags flags)
d->exit = false;
++d->threadData->loopLevel;
d->threadData->eventLoops.push(this);
+ locker.unlock();
// remove posted quit events when entering a new event loop
QCoreApplication *app = QCoreApplication::instance();
@@ -205,6 +208,7 @@ int QEventLoop::exec(ProcessEventsFlags flags)
"reimplement QApplication::notify() and catch all exceptions there.\n");
// copied from below
+ locker.relock();
QEventLoop *eventLoop = d->threadData->eventLoops.pop();
Q_ASSERT_X(eventLoop == this, "QEventLoop::exec()", "internal error");
Q_UNUSED(eventLoop); // --release warning
@@ -216,6 +220,7 @@ int QEventLoop::exec(ProcessEventsFlags flags)
#endif
// copied above
+ locker.relock();
QEventLoop *eventLoop = d->threadData->eventLoops.pop();
Q_ASSERT_X(eventLoop == this, "QEventLoop::exec()", "internal error");
Q_UNUSED(eventLoop); // --release warning
diff --git a/src/corelib/thread/qthread_unix.cpp b/src/corelib/thread/qthread_unix.cpp
index 891ac77..5e0d2a2 100644
--- a/src/corelib/thread/qthread_unix.cpp
+++ b/src/corelib/thread/qthread_unix.cpp
@@ -327,7 +327,10 @@ void *QThreadPrivate::start(void *arg)
set_thread_data(data);
data->ref();
- data->quitNow = false;
+ {
+ QMutexLocker locker(&thr->d_func()->mutex);
+ data->quitNow = thr->d_func()->exited;
+ }
// ### TODO: allow the user to create a custom event dispatcher
createEventDispatcher(data);
diff --git a/src/corelib/thread/qthread_win.cpp b/src/corelib/thread/qthread_win.cpp
index cb2d1a9..f2d1310 100644
--- a/src/corelib/thread/qthread_win.cpp
+++ b/src/corelib/thread/qthread_win.cpp
@@ -298,7 +298,10 @@ unsigned int __stdcall QThreadPrivate::start(void *arg)
QThread::setTerminationEnabled(false);
- data->quitNow = false;
+ {
+ QMutexLocker locker(&thr->d_func()->mutex);
+ data->quitNow = !thr->d_func()->exited;
+ }
// ### TODO: allow the user to create a custom event dispatcher
createEventDispatcher(data);
diff --git a/tests/auto/qthread/tst_qthread.cpp b/tests/auto/qthread/tst_qthread.cpp
index 19c6c16..c69052e 100644
--- a/tests/auto/qthread/tst_qthread.cpp
+++ b/tests/auto/qthread/tst_qthread.cpp
@@ -113,6 +113,7 @@ private slots:
void wait3_slowDestructor();
void destroyFinishRace();
void startFinishRace();
+ void startAndQuitCustomEventLoop();
void stressTest();
};
@@ -1150,5 +1151,20 @@ void tst_QThread::startFinishRace()
}
}
+void tst_QThread::startAndQuitCustomEventLoop()
+{
+ struct Thread : QThread {
+ void run() { QEventLoop().exec(); }
+ };
+
+ for (int i = 0; i < 5; i++) {
+ Thread t;
+ t.start();
+ t.quit();
+ t.wait();
+ }
+}
+
+
QTEST_MAIN(tst_QThread)
#include "tst_qthread.moc"