Commit a8a9eb10 authored by Waqar Ahmed's avatar Waqar Ahmed
Browse files

Handle SIGINT/SIGTERM to prevent accidental data loss

(linux only)

BUG: 445016
parent 64c184b8
Pipeline #144019 failed with stage
in 3 minutes and 4 seconds
......@@ -44,6 +44,8 @@ target_link_libraries(
KF5::DBusAddons
KF5::Crash
KF5::TextWidgets
PRIVATE
kateshared
)
if(KF5Activities_FOUND)
......
......@@ -32,6 +32,7 @@
#include <QUrl>
#include <QVariant>
#include <signal_watcher.h>
#include <urlinfo.h>
#ifdef USE_QT_SINGLE_APP
......@@ -98,6 +99,21 @@ int main(int argc, char **argv)
QApplication app(argc, argv);
#endif
#ifdef Q_OS_UNIX
/**
* Set up signal handler for SIGINT and SIGTERM
*/
SignalWatcher sigWatcher;
QObject::connect(&sigWatcher, &SignalWatcher::unixSignal, [](SignalWatcher::Signal) {
printf("Shutting down...\n");
auto app = KateApp::self();
if (app) {
app->shutdownKate(app->activeKateMainWindow());
}
qApp->quit();
});
#endif
/**
* For Windows and macOS: use Breeze if available
* Of all tested styles that works the best for us
......
add_library(kateshared STATIC
quickdialog.cpp
signal_watcher.cpp
)
target_include_directories(kateshared PUBLIC
......
/*
SPDX-FileCopyrightText: 2021 Waqar Ahmed <waqar.17a@gmail.com>
SPDX-License-Identifier: LGPL-2.0-or-later
*/
#include "signal_watcher.h"
#include <QSocketNotifier>
#include <signal.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <unistd.h>
#if defined(Q_OS_UNIX)
static int sigIntFd[2] = {0, 0};
static int sigTermFd[2] = {0, 0};
static void intSignalHandler(int)
{
char a = 1;
::write(sigIntFd[0], &a, sizeof(a));
}
static void termSignalHandler(int)
{
char a = 1;
::write(sigTermFd[0], &a, sizeof(a));
}
static bool setup_unix_signal_handlers()
{
struct sigaction sigInt;
struct sigaction term;
sigInt.sa_handler = intSignalHandler;
sigemptyset(&sigInt.sa_mask);
sigInt.sa_flags = 0;
sigInt.sa_flags |= SA_RESTART;
if (sigaction(SIGINT, &sigInt, nullptr) != 0)
return false;
term.sa_handler = termSignalHandler;
sigemptyset(&term.sa_mask);
term.sa_flags = 0;
term.sa_flags |= SA_RESTART;
if (sigaction(SIGTERM, &term, nullptr) != 0)
return false;
return true;
}
SignalWatcher::SignalWatcher(QObject *parent)
: QObject(parent)
{
if (setup_unix_signal_handlers()) {
if (::socketpair(AF_UNIX, SOCK_STREAM, 0, sigIntFd))
qWarning("Couldn't create INT socketpair");
if (::socketpair(AF_UNIX, SOCK_STREAM, 0, sigTermFd))
qWarning("Couldn't create TERM socketpair");
m_sigIntSocketNotifier = new QSocketNotifier(sigIntFd[1], QSocketNotifier::Read, this);
connect(m_sigIntSocketNotifier, &QSocketNotifier::activated, this, &SignalWatcher::handleSigInt);
m_sigIntSocketNotifier->setEnabled(true);
m_sigTermSocketNotifier = new QSocketNotifier(sigTermFd[1], QSocketNotifier::Read, this);
connect(m_sigTermSocketNotifier, &QSocketNotifier::activated, this, &SignalWatcher::handleSigTerm);
m_sigTermSocketNotifier->setEnabled(true);
} else {
printf("Failed to setup signal handler\n");
}
}
void SignalWatcher::handleSigInt()
{
m_sigIntSocketNotifier->setEnabled(false);
char tmp{};
::read(sigIntFd[1], &tmp, sizeof(tmp));
Q_EMIT unixSignal(Signal_Interrupt);
m_sigIntSocketNotifier->setEnabled(true);
}
void SignalWatcher::handleSigTerm()
{
m_sigTermSocketNotifier->setEnabled(false);
char tmp{};
::read(sigTermFd[1], &tmp, sizeof(tmp));
Q_EMIT unixSignal(Signal_Terminate);
m_sigTermSocketNotifier->setEnabled(true);
}
#endif
/*
SPDX-FileCopyrightText: 2021 Waqar Ahmed <waqar.17a@gmail.com>
SPDX-License-Identifier: LGPL-2.0-or-later
*/
#ifndef KATE_SIG_WATCHER_H
#define KATE_SIG_WATCHER_H
#include <QObject>
class SignalWatcher : public QObject
{
Q_OBJECT
#if defined(Q_OS_UNIX)
public:
explicit SignalWatcher(QObject *parent = nullptr);
~SignalWatcher() = default;
void watchForSignal(int signal);
enum Signal { Signal_Interrupt = 0, Signal_Terminate };
Q_SIGNALS:
void unixSignal(Signal signal);
private Q_SLOTS:
void handleSigInt();
void handleSigTerm();
private:
class QSocketNotifier *m_sigIntSocketNotifier;
class QSocketNotifier *m_sigTermSocketNotifier;
#endif // defined(Q_OS_UNIX)
};
#endif
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment