diff options
author | Timothy Pearson <kb9vqf@pearsoncomputing.net> | 2015-04-12 16:34:00 -0500 |
---|---|---|
committer | Timothy Pearson <kb9vqf@pearsoncomputing.net> | 2015-04-12 16:34:00 -0500 |
commit | 85126bf580edb675048843910c0e0c1c56c9ff89 (patch) | |
tree | ff20456bfbf57b108f2e105713694d530194cdc9 /kdesktop/lockeng.cc | |
parent | 751c96f9b1fc01675a1a9d34831104f98adfd84f (diff) | |
download | tdebase-85126bf580edb675048843910c0e0c1c56c9ff89.tar.gz tdebase-85126bf580edb675048843910c0e0c1c56c9ff89.zip |
Fix sporadic kdesktop hang due to unsafe usage of asynchronous POSIX signals in the main GUI thread
Diffstat (limited to 'kdesktop/lockeng.cc')
-rw-r--r-- | kdesktop/lockeng.cc | 67 |
1 files changed, 48 insertions, 19 deletions
diff --git a/kdesktop/lockeng.cc b/kdesktop/lockeng.cc index 8e59b9e72..6ce26cf4e 100644 --- a/kdesktop/lockeng.cc +++ b/kdesktop/lockeng.cc @@ -18,6 +18,7 @@ #include <tdelocale.h> #include <tqfile.h> #include <tqtimer.h> +#include <tqeventloop.h> #include <dcopclient.h> #include <assert.h> @@ -49,13 +50,13 @@ SaverEngine* m_masterSaverEngine = NULL; static void sigusr1_handler(int) { if (m_masterSaverEngine) { - m_masterSaverEngine->slotLockProcessWaiting(); + m_masterSaverEngine->m_threadHelperObject->slotLockProcessWaiting(); } } static void sigusr2_handler(int) { if (m_masterSaverEngine) { - m_masterSaverEngine->slotLockProcessFullyActivated(); + m_masterSaverEngine->m_threadHelperObject->slotLockProcessFullyActivated(); } } static void sigttin_handler(int) @@ -114,6 +115,14 @@ SaverEngine::SaverEngine() mXAutoLock = 0; mEnabled = false; + m_helperThread = new TQEventLoopThread; + m_helperThread->start(); + m_threadHelperObject = new SaverEngineThreadHelperObject; + m_threadHelperObject->moveToThread(m_helperThread); + connect(this, TQT_SIGNAL(terminateHelperThread()), m_threadHelperObject, TQT_SLOT(terminateThread())); + connect(m_threadHelperObject, TQT_SIGNAL(lockProcessWaiting()), this, TQT_SLOT(lockProcessWaiting())); + connect(m_threadHelperObject, TQT_SIGNAL(lockProcessFullyActivated()), this, TQT_SLOT(lockProcessFullyActivated())); + connect(&mLockProcess, TQT_SIGNAL(processExited(TDEProcess *)), TQT_SLOT(lockProcessExited())); @@ -138,6 +147,13 @@ SaverEngine::SaverEngine() kdDebug( 1204 ) << "Failed to start kdesktop_lock!" << endl; } + // Prevent kdesktop_lock signals from being handled by the wrong (GUI) thread + sigemptyset(&mThreadBlockSet); + sigaddset(&mThreadBlockSet, SIGUSR1); + sigaddset(&mThreadBlockSet, SIGUSR2); + sigaddset(&mThreadBlockSet, SIGTTIN); + pthread_sigmask(SIG_BLOCK, &mThreadBlockSet, NULL); + dBusConnect(); } @@ -159,6 +175,11 @@ SaverEngine::~SaverEngine() // Restore X screensaver parameters XSetScreenSaver(tqt_xdisplay(), mXTimeout, mXInterval, mXBlanking, mXExposures); + + terminateHelperThread(); + m_helperThread->wait(); + delete m_threadHelperObject; + delete m_helperThread; } //--------------------------------------------------------------------------- @@ -557,14 +578,19 @@ void SaverEngine::lockProcessExited() } } -void SaverEngine::slotLockProcessWaiting() +void SaverEngineThreadHelperObject::slotLockProcessWaiting() { // lockProcessWaiting cannot be called directly from a signal handler, as it will hang in certain obscure circumstances // Instead we use a single-shot timer to immediately call lockProcessWaiting once control has returned to the Qt main loop - TQTimer::singleShot(0, this, SLOT(lockProcessWaiting())); + lockProcessWaiting(); +} + +void SaverEngineThreadHelperObject::slotLockProcessFullyActivated() +{ + lockProcessFullyActivated(); } -void SaverEngine::slotLockProcessFullyActivated() +void SaverEngine::lockProcessFullyActivated() { mState = Saving; @@ -795,7 +821,8 @@ void SaverEngine::handleDBusSignal(const TQT_DBusMessage& msg) { bool SaverEngine::waitForLockProcessStart() { sigset_t new_mask; - sigset_t orig_mask; + sigset_t empty_mask; + sigemptyset(&empty_mask); // wait for SIGUSR1, SIGUSR2, SIGTTIN, SIGCHLD sigemptyset(&new_mask); @@ -804,30 +831,32 @@ bool SaverEngine::waitForLockProcessStart() { sigaddset(&new_mask, SIGTTIN); sigaddset(&new_mask, SIGCHLD); - sigprocmask(SIG_BLOCK, &new_mask, &orig_mask); + pthread_sigmask(SIG_BLOCK, &new_mask, NULL); while ((mLockProcess.isRunning()) && (!mSaverProcessReady)) { - sigsuspend(&orig_mask); + sigsuspend(&empty_mask); } - sigprocmask(SIG_UNBLOCK, &new_mask, NULL); + pthread_sigmask(SIG_UNBLOCK, &new_mask, NULL); return mLockProcess.isRunning(); } bool SaverEngine::waitForLockEngage() { - sigset_t new_mask; - sigset_t orig_mask; + sigset_t empty_mask; + sigemptyset(&empty_mask); // wait for SIGUSR1, SIGUSR2, SIGTTIN - sigemptyset(&new_mask); - sigaddset(&new_mask, SIGUSR1); - sigaddset(&new_mask, SIGUSR2); - sigaddset(&new_mask, SIGTTIN); - - sigprocmask(SIG_BLOCK, &new_mask, &orig_mask); + pthread_sigmask(SIG_BLOCK, &mThreadBlockSet, NULL); while ((mLockProcess.isRunning()) && (mState != Waiting) && (mState != Saving)) { - sigsuspend(&orig_mask); + sigsuspend(&empty_mask); } - sigprocmask(SIG_UNBLOCK, &new_mask, NULL); + pthread_sigmask(SIG_UNBLOCK, &mThreadBlockSet, NULL); return mLockProcess.isRunning(); +} + +void SaverEngineThreadHelperObject::terminateThread() { + TQEventLoop* eventLoop = TQApplication::eventLoop(); + if (eventLoop) { + eventLoop->exit(0); + } }
\ No newline at end of file |