diff options
author | Miikka Heikkinen <miikka.heikkinen@digia.com> | 2010-09-15 07:30:55 (GMT) |
---|---|---|
committer | Miikka Heikkinen <miikka.heikkinen@digia.com> | 2010-09-15 08:13:52 (GMT) |
commit | f9a3f15376d0c0cddc4ab023d2421859847df56b (patch) | |
tree | 8ef65acc9551ffb9756af360323a927c6ba89fce /src | |
parent | 05ab8ad1577fc038aa2b3bd96cedda54e6a64979 (diff) | |
download | Qt-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')
-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; } |