✨ feat: implement signal handling for graceful shutdown using signalfd and QSocketNotifier
This commit is contained in:
+44
-2
@@ -1,9 +1,15 @@
|
|||||||
#include <qapplication.h>
|
|
||||||
#include <qobject.h>
|
#include <qobject.h>
|
||||||
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QQmlApplicationEngine>
|
#include <QQmlApplicationEngine>
|
||||||
#include <QQmlContext>
|
#include <QQmlContext>
|
||||||
|
#include <QSocketNotifier>
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#include <signal.h>
|
||||||
|
#include <sys/signalfd.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
}
|
||||||
|
|
||||||
#include "Core/Provider/bootstrap.hpp"
|
#include "Core/Provider/bootstrap.hpp"
|
||||||
#include "Core/Provider/carousel.hpp"
|
#include "Core/Provider/carousel.hpp"
|
||||||
@@ -20,7 +26,22 @@ int main(int argc, char* argv[]) {
|
|||||||
// 1. QQmlApplicationEngine (with all QML objects)
|
// 1. QQmlApplicationEngine (with all QML objects)
|
||||||
// 2. provider (manages states and connections)
|
// 2. provider (manages states and connections)
|
||||||
// 3. bootstrap (manages lifecycle of all managers)
|
// 3. bootstrap (manages lifecycle of all managers)
|
||||||
// 4. QApplication
|
// 4. QSocketNotifier (receives signals for graceful shutdown)
|
||||||
|
// 5. QApplication
|
||||||
|
|
||||||
|
// Mask signals for graceful shutdown
|
||||||
|
sigset_t mask;
|
||||||
|
sigemptyset(&mask);
|
||||||
|
sigaddset(&mask, SIGINT);
|
||||||
|
sigaddset(&mask, SIGHUP);
|
||||||
|
sigaddset(&mask, SIGTERM);
|
||||||
|
sigaddset(&mask, SIGUSR1);
|
||||||
|
sigaddset(&mask, SIGUSR2);
|
||||||
|
if (pthread_sigmask(SIG_BLOCK, &mask, nullptr) == -1) {
|
||||||
|
// Logger is yet to be initialized, but is still usable with default behavior
|
||||||
|
WR_CRITICAL(QString("Failed to block signals: %1").arg(strerror(errno)));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
QApplication a(argc, argv);
|
QApplication a(argc, argv);
|
||||||
a.setApplicationName(APP_NAME);
|
a.setApplicationName(APP_NAME);
|
||||||
@@ -35,6 +56,27 @@ int main(int argc, char* argv[]) {
|
|||||||
{
|
{
|
||||||
Logger::init();
|
Logger::init();
|
||||||
|
|
||||||
|
// Create signalfd to receive signals in the Qt event loop
|
||||||
|
int sfd = signalfd(-1, &mask, SFD_NONBLOCK | SFD_CLOEXEC);
|
||||||
|
if (sfd == -1) {
|
||||||
|
WR_CRITICAL(QString("Failed to create signalfd: %1").arg(strerror(errno)));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
QSocketNotifier notifier(sfd, QSocketNotifier::Read, &a);
|
||||||
|
|
||||||
|
QObject::connect(
|
||||||
|
¬ifier,
|
||||||
|
&QSocketNotifier::activated,
|
||||||
|
&a,
|
||||||
|
[sfd, &a]() {
|
||||||
|
struct signalfd_siginfo fdsi;
|
||||||
|
ssize_t s = read(sfd, &fdsi, sizeof(struct signalfd_siginfo));
|
||||||
|
if (s == sizeof(struct signalfd_siginfo)) {
|
||||||
|
WR_DEBUG(QString("Received signal: %1").arg(fdsi.ssi_signo));
|
||||||
|
a.quit();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
AppOptions options;
|
AppOptions options;
|
||||||
options.parseArgs(a);
|
options.parseArgs(a);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user