diff options
author | Murray Read <ext-murray.2.read@nokia.com> | 2012-02-06 11:33:07 (GMT) |
---|---|---|
committer | Qt by Nokia <qt-info@nokia.com> | 2012-02-08 00:52:00 (GMT) |
commit | 4490850b9286d9b01fab9bc8900deb1598398f2e (patch) | |
tree | 24868d540c24316f2c1d91d0bc9f797236aa6817 /src/corelib/kernel | |
parent | f343fc7c0844fc33886f3e25d49e043062c06e7a (diff) | |
download | Qt-4490850b9286d9b01fab9bc8900deb1598398f2e.zip Qt-4490850b9286d9b01fab9bc8900deb1598398f2e.tar.gz Qt-4490850b9286d9b01fab9bc8900deb1598398f2e.tar.bz2 |
Handling adopted thread death with active timers on Symbian
Timers are thread local objects on Symbian. When the adopted thread
monitor tries to tidy up a thread, any existing qt timers will be
cleaned up. But that has to be done very carefully without touching the
underlying symbian timer objects.
Checks are added to make sure the Symbian timers are only touched in
the correct thread.
Task-number: ou1cimx1#960478
Change-Id: If16750b455aa576aa9f2d93657a3627d18060272
Reviewed-by: Shane Kearns <ext-shane.2.kearns@nokia.com>
Diffstat (limited to 'src/corelib/kernel')
-rw-r--r-- | src/corelib/kernel/qeventdispatcher_symbian.cpp | 28 | ||||
-rw-r--r-- | src/corelib/kernel/qeventdispatcher_symbian_p.h | 1 |
2 files changed, 23 insertions, 6 deletions
diff --git a/src/corelib/kernel/qeventdispatcher_symbian.cpp b/src/corelib/kernel/qeventdispatcher_symbian.cpp index 637408e..4930a16 100644 --- a/src/corelib/kernel/qeventdispatcher_symbian.cpp +++ b/src/corelib/kernel/qeventdispatcher_symbian.cpp @@ -157,6 +157,7 @@ private: QActiveObject::QActiveObject(TInt priority, QEventDispatcherSymbian *dispatcher) : CActive(priority), m_dispatcher(dispatcher), + m_threadData(QThreadData::current()), m_hasAlreadyRun(false), m_hasRunAgain(false), m_iterationCount(1) @@ -258,18 +259,32 @@ QTimerActiveObject::QTimerActiveObject(QEventDispatcherSymbian *dispatcher, Symb QTimerActiveObject::~QTimerActiveObject() { Cancel(); - m_rTimer.Close(); //close of null handle is safe + // deletion in the wrong thread (eg adoptedThreadMonitor thread) must avoid using the RTimer, which is local + // to the thread it was created in. + if (QThreadData::current() == m_threadData) + m_rTimer.Close(); //close of null handle is safe } void QTimerActiveObject::DoCancel() { - if (m_timerInfo->interval > 0) { - m_rTimer.Cancel(); + // RTimer is thread local and cannot be cancelled outside of the thread it was created in + if (QThreadData::current() == m_threadData) { + if (m_timerInfo->interval > 0) { + m_rTimer.Cancel(); + } else { + if (iStatus.Int() == KRequestPending) { + TRequestStatus *status = &iStatus; + QEventDispatcherSymbian::RequestComplete(status, KErrNone); + } + } } else { - if (iStatus.Int() == KRequestPending) { - TRequestStatus *status = &iStatus; - QEventDispatcherSymbian::RequestComplete(status, KErrNone); + // Cancel requires a signal to continue, we're in the wrong thread to use the RTimer + if (m_threadData->symbian_thread_handle.ExitType() == EExitPending) { + // owner thread is still running, it will receive a stray event if the timer fires now. + qFatal("QTimerActiveObject cancelled from wrong thread"); } + TRequestStatus *status = &iStatus; + User::RequestComplete(status, KErrCancel); } } @@ -358,6 +373,7 @@ void QTimerActiveObject::Start() if (m_timerInfo->interval > 0) { if (!m_rTimer.Handle()) { qt_symbian_throwIfError(m_rTimer.CreateLocal()); + m_threadData = QThreadData::current(); } m_timeoutTimer.start(); m_expectedTimeSinceLastEvent = 0; diff --git a/src/corelib/kernel/qeventdispatcher_symbian_p.h b/src/corelib/kernel/qeventdispatcher_symbian_p.h index 4173862..c520d12 100644 --- a/src/corelib/kernel/qeventdispatcher_symbian_p.h +++ b/src/corelib/kernel/qeventdispatcher_symbian_p.h @@ -88,6 +88,7 @@ public: void reactivateAndComplete(); protected: QEventDispatcherSymbian *m_dispatcher; + QThreadData *m_threadData; private: bool m_hasAlreadyRun : 1; |