diff options
-rw-r--r-- | src/corelib/thread/qthread_unix.cpp | 35 |
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(¤t_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; } |