summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorOlivier Goffart <olivier.goffart@nokia.com>2010-11-04 14:52:12 (GMT)
committerOlivier Goffart <olivier.goffart@nokia.com>2010-11-22 14:09:07 (GMT)
commita43583e0221311b7fe666726ab668e41c5e4bba2 (patch)
tree1a3a2db7a834c35b0b0c6e511e06193b95c95dbc /src
parent5e13c65b7083ba6a28820a82f2fa19ca8c1569b0 (diff)
downloadQt-a43583e0221311b7fe666726ab668e41c5e4bba2.zip
Qt-a43583e0221311b7fe666726ab668e41c5e4bba2.tar.gz
Qt-a43583e0221311b7fe666726ab668e41c5e4bba2.tar.bz2
QThreadPrivate::finish should not keep mutex locked when calling signals
This fix the deadlock shown in the new test wait3_slowDestructor Add a test for QThread::wait(timeout) Task-number: QTBUG-15030 Reviewed-by: Joao Reviewed-by: Brad
Diffstat (limited to 'src')
-rw-r--r--src/corelib/thread/qthread_unix.cpp36
-rw-r--r--src/corelib/thread/qthread_win.cpp29
2 files changed, 37 insertions, 28 deletions
diff --git a/src/corelib/thread/qthread_unix.cpp b/src/corelib/thread/qthread_unix.cpp
index f508c0a..f409256 100644
--- a/src/corelib/thread/qthread_unix.cpp
+++ b/src/corelib/thread/qthread_unix.cpp
@@ -333,40 +333,44 @@ void QThreadPrivate::finish(void *arg)
{
QThread *thr = reinterpret_cast<QThread *>(arg);
QThreadPrivate *d = thr->d_func();
+
#ifdef Q_OS_SYMBIAN
- if (lockAnyway)
+ QMutexLocker locker(lockAnyway ? &d->mutex : 0);
+#else
+ QMutexLocker locker(&d->mutex);
#endif
- d->mutex.lock();
+
d->priority = QThread::InheritPriority;
- d->running = false;
- d->finished = true;
- if (d->terminated)
+ bool terminated = d->terminated;
+ void *data = &d->data->tls;
+ locker.unlock();
+ if (terminated)
emit thr->terminated();
- d->terminated = false;
emit thr->finished();
QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
+ QThreadStorageData::finish((void **)data);
+ locker.relock();
+ d->terminated = false;
- if (d->data->eventDispatcher) {
- d->data->eventDispatcher->closingDown();
- QAbstractEventDispatcher *eventDispatcher = d->data->eventDispatcher;
+ QAbstractEventDispatcher *eventDispatcher = d->data->eventDispatcher;
+ if (eventDispatcher) {
d->data->eventDispatcher = 0;
+ locker.unlock();
+ eventDispatcher->closingDown();
delete eventDispatcher;
+ locker.relock();
}
- void *data = &d->data->tls;
- QThreadStorageData::finish((void **)data);
-
d->thread_id = 0;
#ifdef Q_OS_SYMBIAN
if (closeNativeHandle)
d->data->symbian_thread_handle.Close();
#endif
+ d->running = false;
+ d->finished = true;
+
d->thread_done.wakeAll();
-#ifdef Q_OS_SYMBIAN
- if (lockAnyway)
-#endif
- d->mutex.unlock();
}
diff --git a/src/corelib/thread/qthread_win.cpp b/src/corelib/thread/qthread_win.cpp
index 4a967ed..3706da8 100644
--- a/src/corelib/thread/qthread_win.cpp
+++ b/src/corelib/thread/qthread_win.cpp
@@ -323,25 +323,32 @@ void QThreadPrivate::finish(void *arg, bool lockAnyway)
QThread *thr = reinterpret_cast<QThread *>(arg);
QThreadPrivate *d = thr->d_func();
- if (lockAnyway)
- d->mutex.lock();
+ QMutexLocker locker(lockAnyway ? &d->mutex : 0);
d->priority = QThread::InheritPriority;
- d->running = false;
- d->finished = true;
- if (d->terminated)
+ bool terminated = d->terminated;
+ void **tls_data = reinterpret_cast<void **>(&d->data->tls);
+ locker.unlock();
+ if (terminated)
emit thr->terminated();
- d->terminated = false;
emit thr->finished();
QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
+ QThreadStorageData::finish(tls_data);
+ locker.relock();
+
+ d->terminated = false;
- if (d->data->eventDispatcher) {
- d->data->eventDispatcher->closingDown();
- QAbstractEventDispatcher *eventDispatcher = d->data->eventDispatcher;
+ QAbstractEventDispatcher *eventDispatcher = d->data->eventDispatcher;
+ if (eventDispatcher) {
d->data->eventDispatcher = 0;
+ locker.unlock();
+ eventDispatcher->closingDown();
delete eventDispatcher;
+ locker.relock();
}
- QThreadStorageData::finish(reinterpret_cast<void **>(&d->data->tls));
+ d->running = false;
+ d->finished = true;
+
if (!d->waiters) {
CloseHandle(d->handle);
@@ -350,8 +357,6 @@ void QThreadPrivate::finish(void *arg, bool lockAnyway)
d->id = 0;
- if (lockAnyway)
- d->mutex.unlock();
}
/**************************************************************************