summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/corelib/kernel/qeventdispatcher_symbian.cpp10
-rw-r--r--src/corelib/kernel/qeventdispatcher_symbian_p.h3
-rw-r--r--src/corelib/thread/qthread_symbian.cpp8
3 files changed, 21 insertions, 0 deletions
diff --git a/src/corelib/kernel/qeventdispatcher_symbian.cpp b/src/corelib/kernel/qeventdispatcher_symbian.cpp
index 79f2596..471028e 100644
--- a/src/corelib/kernel/qeventdispatcher_symbian.cpp
+++ b/src/corelib/kernel/qeventdispatcher_symbian.cpp
@@ -194,6 +194,7 @@ void QActiveObject::reactivateAndComplete()
QWakeUpActiveObject::QWakeUpActiveObject(QEventDispatcherSymbian *dispatcher)
: QActiveObject(WAKE_UP_PRIORITY, dispatcher)
{
+ m_hostThreadId = RThread().Id();
CActiveScheduler::Add(this);
iStatus = KRequestPending;
SetActive();
@@ -209,6 +210,15 @@ void QWakeUpActiveObject::DoCancel()
if (iStatus.Int() == KRequestPending) {
TRequestStatus *status = &iStatus;
QEventDispatcherSymbian::RequestComplete(status, KErrNone);
+ } else if (IsActive() && m_hostThreadId != RThread().Id()) {
+ // This is being cancelled in the adopted monitor thread, which can happen if an adopted thread with
+ // an event loop has exited. The event loop creates an event dispatcher with this active object, which may be complete but not run on exit.
+ // We force a cancellation in this thread, because a) the object cannot be deleted while active and b) without a cancellation
+ // the thread semaphore will be one count down.
+ // It is possible for this problem to affect other active objects. They symptom would be that finished signals
+ // from adopted threads are not sent, or they arrive much later than they should.
+ TRequestStatus *status = &iStatus;
+ User::RequestComplete(status, KErrNone);
}
}
diff --git a/src/corelib/kernel/qeventdispatcher_symbian_p.h b/src/corelib/kernel/qeventdispatcher_symbian_p.h
index e07d475..6e04bb1 100644
--- a/src/corelib/kernel/qeventdispatcher_symbian_p.h
+++ b/src/corelib/kernel/qeventdispatcher_symbian_p.h
@@ -110,6 +110,9 @@ public:
protected:
void DoCancel();
void RunL();
+
+private:
+ TThreadId m_hostThreadId;
};
struct SymbianTimerInfo : public QSharedData
diff --git a/src/corelib/thread/qthread_symbian.cpp b/src/corelib/thread/qthread_symbian.cpp
index 15e6898..5d8b5cb 100644
--- a/src/corelib/thread/qthread_symbian.cpp
+++ b/src/corelib/thread/qthread_symbian.cpp
@@ -113,6 +113,7 @@ QThreadData *QThreadData::current()
}
data->deref();
}
+ data->isAdopted = true;
data->threadId = QThread::currentThreadId();
if (!QCoreApplicationPrivate::theMainThread)
QCoreApplicationPrivate::theMainThread = data->thread;
@@ -257,6 +258,13 @@ QCAddAdoptedThread* QCAddAdoptedThread::adoptedThreadAdder = 0;
void QCAdoptedThreadMonitor::RunL()
{
+ 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);
+ }
data->deref();
QCAddAdoptedThread::threadDied();
delete this;