Merge pull request #8592 from devsnek/sig-handlers
exit gracefully on sigint/sigterm
This commit is contained in:
parent
1779795d81
commit
9479940a1f
|
@ -8,6 +8,10 @@
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
#include <unistd.h> // for chdir
|
#include <unistd.h> // for chdir
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef __linux__
|
||||||
|
#include <csignal>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
// VFS includes must be before glad as they will conflict with Windows file api, which uses defines.
|
// VFS includes must be before glad as they will conflict with Windows file api, which uses defines.
|
||||||
#include "applets/qt_controller.h"
|
#include "applets/qt_controller.h"
|
||||||
|
@ -259,6 +263,10 @@ GMainWindow::GMainWindow(bool has_broken_vulkan)
|
||||||
config{std::make_unique<Config>(*system)},
|
config{std::make_unique<Config>(*system)},
|
||||||
vfs{std::make_shared<FileSys::RealVfsFilesystem>()},
|
vfs{std::make_shared<FileSys::RealVfsFilesystem>()},
|
||||||
provider{std::make_unique<FileSys::ManualContentProvider>()} {
|
provider{std::make_unique<FileSys::ManualContentProvider>()} {
|
||||||
|
#ifdef __linux__
|
||||||
|
SetupSigInterrupts();
|
||||||
|
#endif
|
||||||
|
|
||||||
Common::Log::Initialize();
|
Common::Log::Initialize();
|
||||||
LoadTranslation();
|
LoadTranslation();
|
||||||
|
|
||||||
|
@ -462,7 +470,13 @@ GMainWindow::~GMainWindow() {
|
||||||
if (render_window->parent() == nullptr) {
|
if (render_window->parent() == nullptr) {
|
||||||
delete render_window;
|
delete render_window;
|
||||||
}
|
}
|
||||||
|
|
||||||
system->GetRoomNetwork().Shutdown();
|
system->GetRoomNetwork().Shutdown();
|
||||||
|
|
||||||
|
#ifdef __linux__
|
||||||
|
::close(sig_interrupt_fds[0]);
|
||||||
|
::close(sig_interrupt_fds[1]);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void GMainWindow::RegisterMetaTypes() {
|
void GMainWindow::RegisterMetaTypes() {
|
||||||
|
@ -1352,6 +1366,52 @@ static void ReleaseWakeLockLinux(QDBusObjectPath lock) {
|
||||||
QString::fromLatin1("org.freedesktop.portal.Request"));
|
QString::fromLatin1("org.freedesktop.portal.Request"));
|
||||||
unlocker.call(QString::fromLatin1("Close"));
|
unlocker.call(QString::fromLatin1("Close"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::array<int, 3> GMainWindow::sig_interrupt_fds{0, 0, 0};
|
||||||
|
|
||||||
|
void GMainWindow::SetupSigInterrupts() {
|
||||||
|
if (sig_interrupt_fds[2] == 1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
socketpair(AF_UNIX, SOCK_STREAM, 0, sig_interrupt_fds.data());
|
||||||
|
sig_interrupt_fds[2] = 1;
|
||||||
|
|
||||||
|
struct sigaction sa;
|
||||||
|
sa.sa_handler = &GMainWindow::HandleSigInterrupt;
|
||||||
|
sigemptyset(&sa.sa_mask);
|
||||||
|
sa.sa_flags = SA_RESETHAND;
|
||||||
|
sigaction(SIGINT, &sa, nullptr);
|
||||||
|
sigaction(SIGTERM, &sa, nullptr);
|
||||||
|
|
||||||
|
sig_interrupt_notifier = new QSocketNotifier(sig_interrupt_fds[1], QSocketNotifier::Read, this);
|
||||||
|
connect(sig_interrupt_notifier, &QSocketNotifier::activated, this,
|
||||||
|
&GMainWindow::OnSigInterruptNotifierActivated);
|
||||||
|
connect(this, &GMainWindow::SigInterrupt, this, &GMainWindow::close);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GMainWindow::HandleSigInterrupt(int sig) {
|
||||||
|
if (sig == SIGINT) {
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calling into Qt directly from a signal handler is not safe,
|
||||||
|
// so wake up a QSocketNotifier with this hacky write call instead.
|
||||||
|
char a = 1;
|
||||||
|
int ret = write(sig_interrupt_fds[0], &a, sizeof(a));
|
||||||
|
(void)ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GMainWindow::OnSigInterruptNotifierActivated() {
|
||||||
|
sig_interrupt_notifier->setEnabled(false);
|
||||||
|
|
||||||
|
char a;
|
||||||
|
int ret = read(sig_interrupt_fds[1], &a, sizeof(a));
|
||||||
|
(void)ret;
|
||||||
|
|
||||||
|
sig_interrupt_notifier->setEnabled(true);
|
||||||
|
|
||||||
|
emit SigInterrupt();
|
||||||
|
}
|
||||||
#endif // __linux__
|
#endif // __linux__
|
||||||
|
|
||||||
void GMainWindow::PreventOSSleep() {
|
void GMainWindow::PreventOSSleep() {
|
||||||
|
|
|
@ -163,6 +163,8 @@ signals:
|
||||||
void WebBrowserExtractOfflineRomFS();
|
void WebBrowserExtractOfflineRomFS();
|
||||||
void WebBrowserClosed(Service::AM::Applets::WebExitReason exit_reason, std::string last_url);
|
void WebBrowserClosed(Service::AM::Applets::WebExitReason exit_reason, std::string last_url);
|
||||||
|
|
||||||
|
void SigInterrupt();
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void OnLoadComplete();
|
void OnLoadComplete();
|
||||||
void OnExecuteProgram(std::size_t program_index);
|
void OnExecuteProgram(std::size_t program_index);
|
||||||
|
@ -251,6 +253,12 @@ private:
|
||||||
void RequestGameResume();
|
void RequestGameResume();
|
||||||
void closeEvent(QCloseEvent* event) override;
|
void closeEvent(QCloseEvent* event) override;
|
||||||
|
|
||||||
|
#ifdef __linux__
|
||||||
|
void SetupSigInterrupts();
|
||||||
|
static void HandleSigInterrupt(int);
|
||||||
|
void OnSigInterruptNotifierActivated();
|
||||||
|
#endif
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void OnStartGame();
|
void OnStartGame();
|
||||||
void OnRestartGame();
|
void OnRestartGame();
|
||||||
|
@ -419,6 +427,9 @@ private:
|
||||||
bool is_tas_recording_dialog_active{};
|
bool is_tas_recording_dialog_active{};
|
||||||
|
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
|
QSocketNotifier* sig_interrupt_notifier;
|
||||||
|
static std::array<int, 3> sig_interrupt_fds;
|
||||||
|
|
||||||
QDBusObjectPath wake_lock{};
|
QDBusObjectPath wake_lock{};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
Reference in New Issue