diff options
author | mread <qt-info@nokia.com> | 2011-03-18 10:42:45 (GMT) |
---|---|---|
committer | mread <qt-info@nokia.com> | 2011-03-18 10:49:21 (GMT) |
commit | a9cb2be8c14317001c0945da84f1a19e1d6ee6c6 (patch) | |
tree | d7d9f62fe53049e6c10afa5df2a18134d4b72e59 /src/corelib/kernel | |
parent | bbbe40631bac44489d35d7ae76a3ccd41b75fe6a (diff) | |
download | Qt-a9cb2be8c14317001c0945da84f1a19e1d6ee6c6.zip Qt-a9cb2be8c14317001c0945da84f1a19e1d6ee6c6.tar.gz Qt-a9cb2be8c14317001c0945da84f1a19e1d6ee6c6.tar.bz2 |
Making Symbian helper threads exit cleanly at app exit
The idle detector thread and the adopted thread monitor thread could
keep an app alive unnecessarily after main had exited, if the app's
main thread was no longer set "process permanent".
The idle detector thread now exits when the QCoreApplication is
destroyed.
The adopted thread monitor thread now exits when there are no more
adopted threads to monitor.
Task-number: QTBUG-18073
Reviewed-by: Shane Kearns
Diffstat (limited to 'src/corelib/kernel')
-rw-r--r-- | src/corelib/kernel/qeventdispatcher_symbian.cpp | 50 |
1 files changed, 40 insertions, 10 deletions
diff --git a/src/corelib/kernel/qeventdispatcher_symbian.cpp b/src/corelib/kernel/qeventdispatcher_symbian.cpp index 53796be..4c01bde 100644 --- a/src/corelib/kernel/qeventdispatcher_symbian.cpp +++ b/src/corelib/kernel/qeventdispatcher_symbian.cpp @@ -43,6 +43,7 @@ #include <private/qthread_p.h> #include <qcoreapplication.h> #include <private/qcoreapplication_p.h> +#include <qsemaphore.h> #include <unistd.h> #include <errno.h> @@ -654,34 +655,54 @@ class QIdleDetectorThread { public: QIdleDetectorThread() - : m_state(STATE_RUN), m_stop(false) + : m_state(STATE_RUN), m_stop(false), m_running(false) { - qt_symbian_throwIfError(m_lock.CreateLocal(0)); + start(); + } + + ~QIdleDetectorThread() + { + stop(); + } + + void start() + { + QMutexLocker lock(&m_mutex); + if (m_running) + return; + m_stop = false; + m_state = STATE_RUN; TInt err = m_idleDetectorThread.Create(KNullDesC(), &idleDetectorThreadFunc, 1024, &User::Allocator(), this); if (err != KErrNone) - m_lock.Close(); - qt_symbian_throwIfError(err); + return; // Fail silently on error. Next kick will try again. Exception might stop the event being processed m_idleDetectorThread.SetPriority(EPriorityAbsoluteBackgroundNormal); m_idleDetectorThread.Resume(); + m_running = true; + // get a callback from QCoreApplication destruction to stop this thread + qAddPostRoutine(StopIdleDetectorThread); } - ~QIdleDetectorThread() + void stop() { + QMutexLocker lock(&m_mutex); + if (!m_running) + return; // close down the idle thread because if corelib is loaded temporarily, this would leak threads into the host process m_stop = true; - m_lock.Signal(); + m_kick.release(); m_idleDetectorThread.SetPriority(EPriorityNormal); TRequestStatus s; m_idleDetectorThread.Logon(s); User::WaitForRequest(s); m_idleDetectorThread.Close(); - m_lock.Close(); + m_running = false; } void kick() { + start(); m_state = STATE_KICKED; - m_lock.Signal(); + m_kick.release(); } bool hasRun() @@ -700,20 +721,29 @@ private: void IdleLoop() { while (!m_stop) { - m_lock.Wait(); + m_kick.acquire(); m_state = STATE_RUN; } } + static void StopIdleDetectorThread(); + private: enum IdleStates {STATE_KICKED, STATE_RUN} m_state; bool m_stop; + bool m_running; RThread m_idleDetectorThread; - RSemaphore m_lock; + QSemaphore m_kick; + QMutex m_mutex; }; Q_GLOBAL_STATIC(QIdleDetectorThread, idleDetectorThread); +void QIdleDetectorThread::StopIdleDetectorThread() +{ + idleDetectorThread()->stop(); +} + const int maxBusyTime = 2000; // maximum time we allow idle detector to be blocked before worrying, in milliseconds const int baseDelay = 1000; // minimum delay time used when backing off to allow idling, in microseconds #endif |