Skip to content

Commit f78aab5

Browse files
Handle SIGTERM and SIGKILL (flameshot-org#4091)
* Handle sigint and sigterm when KDSingleApplication is used to prevent stale lock files * fixing windows build * cleanup after more review
1 parent 4f224d9 commit f78aab5

File tree

4 files changed

+134
-5
lines changed

4 files changed

+134
-5
lines changed

src/core/CMakeLists.txt

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,15 @@ target_sources(flameshot PRIVATE
1313
qguiappcurrentscreen.cpp
1414
)
1515

16-
IF (WIN32)
16+
if (USE_KDSINGLEAPPLICATION)
17+
if (NOT WIN32)
18+
target_sources(flameshot PRIVATE
19+
signaldaemon.h
20+
signaldaemon.cpp
21+
)
22+
endif ()
23+
endif ()
24+
25+
if (WIN32)
1726
target_sources(flameshot PRIVATE globalshortcutfilter.h globalshortcutfilter.cpp)
18-
ENDIF ()
27+
endif ()

src/core/signaldaemon.cpp

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
#include "signaldaemon.h"
2+
#include <QApplication>
3+
#include <QSocketNotifier>
4+
#include <csignal>
5+
#include <qdebug.h>
6+
#include <sys/socket.h>
7+
#include <unistd.h>
8+
9+
int SignalDaemon::sigintFd[2];
10+
int SignalDaemon::sigtermFd[2];
11+
12+
SignalDaemon::SignalDaemon(QObject* parent)
13+
: QObject(parent)
14+
{
15+
if (::socketpair(AF_UNIX, SOCK_STREAM, 0, sigintFd))
16+
qFatal("Couldn't create INT socketpair");
17+
18+
if (::socketpair(AF_UNIX, SOCK_STREAM, 0, sigtermFd))
19+
qFatal("Couldn't create TERM socketpair");
20+
snInt = new QSocketNotifier(sigintFd[1], QSocketNotifier::Read, this);
21+
connect(
22+
snInt, SIGNAL(activated(QSocketDescriptor)), this, SLOT(handleSigInt()));
23+
snTerm = new QSocketNotifier(sigtermFd[1], QSocketNotifier::Read, this);
24+
connect(snTerm,
25+
SIGNAL(activated(QSocketDescriptor)),
26+
this,
27+
SLOT(handleSigTerm()));
28+
}
29+
30+
void SignalDaemon::intSignalHandler(int)
31+
{
32+
char msg = 1;
33+
::write(sigintFd[0], &msg, sizeof(msg));
34+
}
35+
36+
void SignalDaemon::termSignalHandler(int)
37+
{
38+
char msg = 1;
39+
::write(sigtermFd[0], &msg, sizeof(msg));
40+
}
41+
42+
void SignalDaemon::handleSigTerm()
43+
{
44+
snTerm->setEnabled(false);
45+
char tmp = 0;
46+
::read(sigtermFd[1], &tmp, sizeof(tmp));
47+
48+
QApplication::quit();
49+
snTerm->setEnabled(true);
50+
}
51+
52+
void SignalDaemon::handleSigInt()
53+
{
54+
snInt->setEnabled(false);
55+
56+
char tmp = 0;
57+
::read(sigintFd[1], &tmp, sizeof(tmp));
58+
59+
QApplication::quit();
60+
61+
snInt->setEnabled(true);
62+
}

src/core/signaldaemon.h

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#include <QObject>
2+
#include <QSocketNotifier>
3+
4+
class SignalDaemon : public QObject
5+
{
6+
Q_OBJECT
7+
8+
public:
9+
SignalDaemon(QObject* parent = 0);
10+
~SignalDaemon() = default;
11+
12+
// Unix signal handlers.
13+
static void intSignalHandler(int unused);
14+
static void termSignalHandler(int unused);
15+
16+
public slots:
17+
// Qt signal handlers.
18+
void handleSigInt();
19+
void handleSigTerm();
20+
21+
private:
22+
static int sigintFd[2];
23+
static int sigtermFd[2];
24+
25+
QSocketNotifier* snInt;
26+
QSocketNotifier* snTerm;
27+
};

src/main.cpp

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@
33

44
#ifdef USE_KDSINGLEAPPLICATION
55
#include "kdsingleapplication.h"
6+
#ifdef Q_OS_UNIX
7+
#include "core/signaldaemon.h"
8+
#include "csignal"
9+
#endif
610
#endif
711

812
#include "abstractlogger.h"
@@ -34,6 +38,31 @@
3438
// Required for saving button list QList<CaptureTool::Type>
3539
Q_DECLARE_METATYPE(QList<int>)
3640

41+
#if defined(USE_KDSINGLEAPPLICATION) && defined(Q_OS_UNIX)
42+
static int setup_unix_signal_handlers()
43+
{
44+
struct sigaction sint, term;
45+
46+
sint.sa_handler = SignalDaemon::intSignalHandler;
47+
sigemptyset(&sint.sa_mask);
48+
sint.sa_flags = 0;
49+
sint.sa_flags |= SA_RESTART;
50+
51+
if (sigaction(SIGINT, &sint, 0))
52+
return 1;
53+
54+
term.sa_handler = SignalDaemon::termSignalHandler;
55+
sigemptyset(&term.sa_mask);
56+
term.sa_flags = 0;
57+
term.sa_flags |= SA_RESTART;
58+
59+
if (sigaction(SIGTERM, &term, 0))
60+
return 2;
61+
62+
return 0;
63+
}
64+
#endif
65+
3766
int requestCaptureAndWait(const CaptureRequest& req)
3867
{
3968
Flameshot* flameshot = Flameshot::instance();
@@ -149,11 +178,13 @@ int main(int argc, char* argv[])
149178
QApplication app(argc, argv);
150179

151180
#ifdef USE_KDSINGLEAPPLICATION
152-
KDSingleApplication kdsa(QStringLiteral("flameshot"));
181+
#ifdef Q_OS_UNIX
182+
setup_unix_signal_handlers();
183+
auto signalDaemon = SignalDaemon();
184+
#endif
185+
auto kdsa = KDSingleApplication(QStringLiteral("flameshot"));
153186

154187
if (!kdsa.isPrimaryInstance()) {
155-
// AbstractLogger::warning()
156-
// << QStringLiteral("Closing second Flameshot instance!");
157188
return 0; // Quit
158189
}
159190
#endif

0 commit comments

Comments
 (0)