summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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;
}