summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMurray Read <ext-murray.2.read@nokia.com>2012-06-18 16:43:19 +0100
committerPasi Pentikäinen <ext-pasi.a.pentikainen@nokia.com>2012-08-22 13:10:44 +0200
commit385c3574c2505e7c7ff9eb5387f95015f27cde7b (patch)
tree6f6ef0ce18654c4696a21d2c00d98b5fe08060a3
parent7fc3d58dedff59b33358041e63d910430b44a1e9 (diff)
Removing potential crashes from out-of-thread cleanup on Symbian4.8.1-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> (cherry picked from commit 1f9168d3839b2081572368b786c263a04955337c)
-rw-r--r--src/corelib/kernel/qeventdispatcher_symbian.cpp3
-rw-r--r--src/corelib/thread/qthread_symbian.cpp38
-rw-r--r--src/gui/kernel/qapplication_s60.cpp9
-rw-r--r--src/gui/text/qfontengine_s60.cpp6
4 files changed, 48 insertions, 8 deletions
diff --git a/src/corelib/kernel/qeventdispatcher_symbian.cpp b/src/corelib/kernel/qeventdispatcher_symbian.cpp
index a4c113b407..c26166b773 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 149da9c3b8..e5246619aa 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(&current_thread_data_key, pthread_in_thread_cleanup);
+}
+
+static void destroy_current_thread_data_key()
+{
+ pthread_once(&current_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(&current_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 358d6adae3..de5000d8e5 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 899b5da2c6..2702ca838a 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