Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/keepassxreboot/keepassxc.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui/Application.cpp')
-rw-r--r--src/gui/Application.cpp68
1 files changed, 68 insertions, 0 deletions
diff --git a/src/gui/Application.cpp b/src/gui/Application.cpp
index d982f22ca..26d9d2283 100644
--- a/src/gui/Application.cpp
+++ b/src/gui/Application.cpp
@@ -17,12 +17,20 @@
*/
#include "Application.h"
+#include "MainWindow.h"
#include <QAbstractNativeEventFilter>
#include <QFileOpenEvent>
+#include <QSocketNotifier>
#include "autotype/AutoType.h"
+#if defined(Q_OS_UNIX)
+#include <signal.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#endif
+
#if defined(Q_OS_UNIX) && !defined(Q_OS_OSX)
class XcbEventFilter : public QAbstractNativeEventFilter
{
@@ -65,12 +73,18 @@ public:
Application::Application(int& argc, char** argv)
: QApplication(argc, argv)
, m_mainWindow(nullptr)
+#ifdef Q_OS_UNIX
+ , m_unixSignalNotifier(nullptr)
+#endif
{
#if defined(Q_OS_UNIX) && !defined(Q_OS_OSX)
installNativeEventFilter(new XcbEventFilter());
#elif defined(Q_OS_WIN)
installNativeEventFilter(new WinEventFilter());
#endif
+#if defined(Q_OS_UNIX)
+ registerUnixSignals();
+#endif
}
void Application::setMainWindow(QWidget* mainWindow)
@@ -98,3 +112,57 @@ bool Application::event(QEvent* event)
return QApplication::event(event);
}
+
+#if defined(Q_OS_UNIX)
+int Application::unixSignalSocket[2];
+
+void Application::registerUnixSignals()
+{
+ int result = ::socketpair(AF_UNIX, SOCK_STREAM, 0, unixSignalSocket);
+ Q_ASSERT(0 == result);
+ if (0 != result) {
+ // do not register handles when socket creation failed, otherwise
+ // application will be unresponsive to signals such as SIGINT or SIGTERM
+ return;
+ }
+
+ QVector<int> const handledSignals = { SIGQUIT, SIGINT, SIGTERM, SIGHUP };
+ for (auto s: handledSignals) {
+ struct sigaction sigAction;
+
+ sigAction.sa_handler = handleUnixSignal;
+ sigemptyset(&sigAction.sa_mask);
+ sigAction.sa_flags = 0 | SA_RESTART;
+ sigaction(s, &sigAction, nullptr);
+ }
+
+ m_unixSignalNotifier = new QSocketNotifier(unixSignalSocket[1], QSocketNotifier::Read, this);
+ connect(m_unixSignalNotifier, SIGNAL(activated(int)), this, SLOT(quitBySignal()));
+}
+
+void Application::handleUnixSignal(int sig)
+{
+ switch (sig) {
+ case SIGQUIT:
+ case SIGINT:
+ case SIGTERM:
+ {
+ char buf = 0;
+ ::write(unixSignalSocket[0], &buf, sizeof(buf));
+ return;
+ }
+ case SIGHUP:
+ return;
+ }
+}
+
+void Application::quitBySignal()
+{
+ m_unixSignalNotifier->setEnabled(false);
+ char buf;
+ ::read(unixSignalSocket[1], &buf, sizeof(buf));
+
+ if (nullptr != m_mainWindow)
+ static_cast<MainWindow*>(m_mainWindow)->appExit();
+}
+#endif