summaryrefslogtreecommitdiffstats
path: root/kdesktop/lockeng.cc
diff options
context:
space:
mode:
authorTimothy Pearson <kb9vqf@pearsoncomputing.net>2015-04-12 16:34:00 -0500
committerTimothy Pearson <kb9vqf@pearsoncomputing.net>2015-04-12 16:34:00 -0500
commit85126bf580edb675048843910c0e0c1c56c9ff89 (patch)
treeff20456bfbf57b108f2e105713694d530194cdc9 /kdesktop/lockeng.cc
parent751c96f9b1fc01675a1a9d34831104f98adfd84f (diff)
downloadtdebase-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.cc67
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