diff options
author | Murray Read <ext-murray.2.read@nokia.com> | 2012-06-18 15:43:19 (GMT) |
---|---|---|
committer | Qt by Nokia <qt-info@nokia.com> | 2012-06-21 09:21:28 (GMT) |
commit | 1f9168d3839b2081572368b786c263a04955337c (patch) | |
tree | 6aa26d42e9df43f3a4ec5b0ea0880fd325e58e1e | |
parent | 4093ae7ae38f6006f7f8c1438e89777144a0c10b (diff) | |
download | Qt-1f9168d3839b2081572368b786c263a04955337c.zip Qt-1f9168d3839b2081572368b786c263a04955337c.tar.gz Qt-1f9168d3839b2081572368b786c263a04955337c.tar.bz2 |
Removing potential crashes from out-of-thread cleanup on Symbian
There have been some crashes seen on Symbian when its
adoptedThreadMonitor attempts to clean up objects created in other, now
dead, threads. Some of these objects simply can't be cleaned up
properly outside of their original thread, so the thread has to be
checked when they are cleaned up, and cleanup skipped in the wrong
thread.
For pthread created threads, we also have the ability to insert cleanup
code during thread shutdown. This was used in the 4.7 implementation of
QThread on Symbian, and is a better solution for pthread based adopted
threads as it gives in-thread cleanup. So the appropriate pthread code
is also used with changes to adoptedThreadMonitor so that it can run
along side the pthread cleanup code.
Change-Id: Iad8207879b1ece62e5cce85f26a616166aa22486
Reviewed-by: Juha Kukkonen <ext-juha.kukkonen@nokia.com>
Reviewed-by: Pasi Pentikäinen <ext-pasi.a.pentikainen@nokia.com>
-rw-r--r-- | src/corelib/kernel/qeventdispatcher_symbian.cpp | 3 | ||||
-rw-r--r-- | src/corelib/thread/qthread_symbian.cpp | 38 | ||||
-rw-r--r-- | src/gui/kernel/qapplication_s60.cpp | 9 | ||||
-rw-r--r-- | src/gui/text/qfontengine_s60.cpp | 6 |
4 files changed, 48 insertions, 8 deletions
diff --git a/src/corelib/kernel/qeventdispatcher_symbian.cpp b/src/corelib/kernel/qeventdispatcher_symbian.cpp index a4c113b..c26166b 100644 --- a/src/corelib/kernel/qeventdispatcher_symbian.cpp +++ b/src/corelib/kernel/qeventdispatcher_symbian.cpp @@ -1041,7 +1041,8 @@ void QEventDispatcherSymbian::closingDown() delete m_completeDeferredAOs; delete m_wakeUpAO; - if (m_activeScheduler) { + // only delete the active scheduler in its own thread + if (m_activeScheduler && QThread::currentThread() == thread()) { delete m_activeScheduler; } } diff --git a/src/corelib/thread/qthread_symbian.cpp b/src/corelib/thread/qthread_symbian.cpp index 149da9c..e524661 100644 --- a/src/corelib/thread/qthread_symbian.cpp +++ b/src/corelib/thread/qthread_symbian.cpp @@ -264,26 +264,58 @@ private: QMutex QCAddAdoptedThread::adoptedThreadMonitorMutex; QCAddAdoptedThread* QCAddAdoptedThread::adoptedThreadAdder = 0; -void QCAdoptedThreadMonitor::RunL() +static void finishAdoptedThread(QThreadData* data, bool closeNativeHandle) { if (data->isAdopted) { QThread *thread = data->thread; Q_ASSERT(thread); QThreadPrivate *thread_p = static_cast<QThreadPrivate *>(QObjectPrivate::get(thread)); - Q_ASSERT(!thread_p->finished); - thread_p->finish(thread); + if (!thread_p->finished) + thread_p->finish(thread, true, closeNativeHandle); + else if (closeNativeHandle && data->symbian_thread_handle.Handle()) + data->symbian_thread_handle.Close(); } +} + +void QCAdoptedThreadMonitor::RunL() +{ + // clean up the thread, or close the handle if that's all that's left + finishAdoptedThread(data, true); data->deref(); QCAddAdoptedThread::threadDied(); delete this; } +static pthread_once_t current_thread_data_once = PTHREAD_ONCE_INIT; +static pthread_key_t current_thread_data_key; + +static void pthread_in_thread_cleanup(void *p) +{ + QThreadData *data = static_cast<QThreadData *>(p); + // clean up the thread, but leave the handle for adoptedThreadMonitor + finishAdoptedThread(data, false); +} + +static void create_current_thread_data_key() +{ + pthread_key_create(¤t_thread_data_key, pthread_in_thread_cleanup); +} + +static void destroy_current_thread_data_key() +{ + pthread_once(¤t_thread_data_once, create_current_thread_data_key); + pthread_key_delete(current_thread_data_key); +} +Q_DESTRUCTOR_FUNCTION(destroy_current_thread_data_key) + void QAdoptedThread::init() { Q_D(QThread); d->thread_id = RThread().Id(); // type operator to TUint init_symbian_thread_handle(d->data->symbian_thread_handle); QCAddAdoptedThread::add(this); + pthread_once(¤t_thread_data_once, create_current_thread_data_key); + pthread_setspecific(current_thread_data_key, get_thread_data()); } /* diff --git a/src/gui/kernel/qapplication_s60.cpp b/src/gui/kernel/qapplication_s60.cpp index 358d6ad..de5000d 100644 --- a/src/gui/kernel/qapplication_s60.cpp +++ b/src/gui/kernel/qapplication_s60.cpp @@ -2980,8 +2980,13 @@ QS60ThreadLocalData::~QS60ThreadLocalData() releaseFuncs[i](); releaseFuncs.clear(); if (!usingCONEinstances) { - delete screenDevice; - wsSession.Close(); + // wserv has a thread specific handle, do not close it, or delete the screenDevice, if it is not open in this thread + THandleInfo handleInfo; + wsSession.HandleInfo(&handleInfo); + if (handleInfo.iNumOpenInThread) { + delete screenDevice; + wsSession.Close(); + } } } diff --git a/src/gui/text/qfontengine_s60.cpp b/src/gui/text/qfontengine_s60.cpp index 899b5da..2702ca8 100644 --- a/src/gui/text/qfontengine_s60.cpp +++ b/src/gui/text/qfontengine_s60.cpp @@ -298,8 +298,10 @@ QFontEngineS60::QFontEngineS60(const QFontDef &request, const QSymbianTypeFaceEx QFontEngineS60::~QFontEngineS60() { - releaseFont(m_originalFont); - releaseFont(m_scaledFont); + if (QThread::currentThread() == thread()) { + releaseFont(m_originalFont); + releaseFont(m_scaledFont); + } } QFixed QFontEngineS60::emSquareSize() const |