summaryrefslogtreecommitdiffstats
path: root/src/corelib
diff options
context:
space:
mode:
authorMiikka Heikkinen <miikka.heikkinen@digia.com>2010-09-15 07:30:55 (GMT)
committerMiikka Heikkinen <miikka.heikkinen@digia.com>2010-09-15 08:13:52 (GMT)
commitf9a3f15376d0c0cddc4ab023d2421859847df56b (patch)
tree8ef65acc9551ffb9756af360323a927c6ba89fce /src/corelib
parent05ab8ad1577fc038aa2b3bd96cedda54e6a64979 (diff)
downloadQt-f9a3f15376d0c0cddc4ab023d2421859847df56b.zip
Qt-f9a3f15376d0c0cddc4ab023d2421859847df56b.tar.gz
Qt-f9a3f15376d0c0cddc4ab023d2421859847df56b.tar.bz2
Do not wait for QThread exit when destroying global statics in Symbian
Symbian kernel will kill all threads except the main one before running destructors on global static objects. Qt gets no notification of these thread terminations, so it'll still think those threads are running and will wait indefinitely for their exit. QThread::wait() now checks if the thread is actually still alive before starting to wait on thread_done wait condition. Task-number: QTBUG-13612 Reviewed-by: Janne Koskinen
Diffstat (limited to 'src/corelib')
-rw-r--r--src/corelib/thread/qthread_unix.cpp35
1 files changed, 29 insertions, 6 deletions
diff --git a/src/corelib/thread/qthread_unix.cpp b/src/corelib/thread/qthread_unix.cpp
index d193b2e..2824e15 100644
--- a/src/corelib/thread/qthread_unix.cpp
+++ b/src/corelib/thread/qthread_unix.cpp
@@ -142,6 +142,20 @@ static void destroy_current_thread_data_key()
}
Q_DESTRUCTOR_FUNCTION(destroy_current_thread_data_key)
+#ifdef Q_OS_SYMBIAN
+static void init_symbian_thread_handle(RThread &thread)
+{
+ thread = RThread();
+ TThreadId threadId = thread.Id();
+ thread.Open(threadId);
+
+ // Make thread handle accessible process wide
+ RThread originalCloser = thread;
+ thread.Duplicate(thread, EOwnerProcess);
+ originalCloser.Close();
+}
+#endif
+
QThreadData *QThreadData::current()
{
pthread_once(&current_thread_data_once, create_current_thread_data_key);
@@ -182,9 +196,7 @@ void QAdoptedThread::init()
Q_D(QThread);
d->thread_id = pthread_self();
#ifdef Q_OS_SYMBIAN
- d->data->symbian_thread_handle = RThread();
- TThreadId threadId = d->data->symbian_thread_handle.Id();
- d->data->symbian_thread_handle.Open(threadId);
+ init_symbian_thread_handle(d->data->symbian_thread_handle);
#endif
}
@@ -244,9 +256,8 @@ void *QThreadPrivate::start(void *arg)
// RThread and pthread_t, we must delay initialization of the RThread
// handle when creating a thread, until we are running in the new thread.
// Here, we pick up the current thread and assign that to the handle.
- data->symbian_thread_handle = RThread();
- TThreadId threadId = data->symbian_thread_handle.Id();
- data->symbian_thread_handle.Open(threadId);
+ init_symbian_thread_handle(data->symbian_thread_handle);
+
// On symbian, threads other than the main thread are non critical by default
// This means a worker thread can crash without crashing the application - to
// use this feature, we would need to use RThread::Logon in the main thread
@@ -657,6 +668,18 @@ bool QThread::wait(unsigned long time)
return true;
while (d->running) {
+#ifdef Q_OS_SYMBIAN
+ // Check if thread still exists. Needed because kernel will kill it without notification
+ // before global statics are deleted at application exit.
+ if (d->data->symbian_thread_handle.Handle()
+ && d->data->symbian_thread_handle.ExitType() != EExitPending) {
+ // Cannot call finish here as wait is typically called from another thread.
+ // It won't be necessary anyway, as we should never get here under normal operations;
+ // all QThreads are EProcessCritical and therefore cannot normally exit
+ // undetected (i.e. panic) as long as all thread control is via QThread.
+ return true;
+ }
+#endif
if (!d->thread_done.wait(locker.mutex(), time))
return false;
}