summaryrefslogtreecommitdiff
path: root/Source
diff options
context:
space:
mode:
authorspycrab <spycrab@users.noreply.github.com>2018-05-22 21:30:54 +0200
committerspycrab <spycrab@users.noreply.github.com>2018-05-28 21:47:46 +0200
commit112a174ae1c4ea3bc7d1592e3f6fc0be7e963f34 (patch)
treee8c1d67402152d8d4148466f2091aac2de3455a6 /Source
parent0e9255c46999865a2d2e8a748ecccdfec7f6d476 (diff)
Qt/Unix: Implement signal handler
Diffstat (limited to 'Source')
-rw-r--r--Source/Core/DolphinQt2/CMakeLists.txt1
-rw-r--r--Source/Core/DolphinQt2/MainWindow.cpp32
-rw-r--r--Source/Core/DolphinQt2/MainWindow.h1
-rw-r--r--Source/Core/DolphinQt2/QtUtils/SignalDaemon.cpp55
-rw-r--r--Source/Core/DolphinQt2/QtUtils/SignalDaemon.h31
5 files changed, 119 insertions, 1 deletions
diff --git a/Source/Core/DolphinQt2/CMakeLists.txt b/Source/Core/DolphinQt2/CMakeLists.txt
index 3d205741b3..d605a2b1a0 100644
--- a/Source/Core/DolphinQt2/CMakeLists.txt
+++ b/Source/Core/DolphinQt2/CMakeLists.txt
@@ -95,6 +95,7 @@ add_executable(dolphin-emu
QtUtils/DoubleClickEventFilter.cpp
QtUtils/ElidedButton.cpp
QtUtils/ImageConverter.cpp
+ QtUtils/SignalDaemon.cpp
QtUtils/WindowActivationEventFilter.cpp
QtUtils/WinIconHelper.cpp
QtUtils/WrapInScrollArea.cpp
diff --git a/Source/Core/DolphinQt2/MainWindow.cpp b/Source/Core/DolphinQt2/MainWindow.cpp
index 90bf1b2d20..3cf69295ae 100644
--- a/Source/Core/DolphinQt2/MainWindow.cpp
+++ b/Source/Core/DolphinQt2/MainWindow.cpp
@@ -1,4 +1,3 @@
-
// Copyright 2015 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
@@ -20,6 +19,12 @@
#include <future>
#include <optional>
+#if defined(__unix__) || defined(__unix) || defined(__APPLE__)
+#include <signal.h>
+
+#include "QtUtils/SignalDaemon.h"
+#endif
+
#include "Common/Version.h"
#include "Core/Boot/Boot.h"
@@ -86,6 +91,23 @@
#include "UICommon/X11Utils.h"
#endif
+#if defined(__unix__) || defined(__unix) || defined(__APPLE__)
+void MainWindow::OnSignal()
+{
+ close();
+}
+
+static void InstallSignalHandler()
+{
+ struct sigaction sa;
+ sa.sa_handler = &SignalDaemon::HandleInterrupt;
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = SA_RESETHAND;
+ sigaction(SIGINT, &sa, nullptr);
+ sigaction(SIGTERM, &sa, nullptr);
+}
+#endif
+
MainWindow::MainWindow(std::unique_ptr<BootParameters> boot_parameters) : QMainWindow(nullptr)
{
setWindowTitle(QString::fromStdString(Common::scm_rev_str));
@@ -109,6 +131,14 @@ MainWindow::MainWindow(std::unique_ptr<BootParameters> boot_parameters) : QMainW
NetPlayInit();
+#if defined(__unix__) || defined(__unix) || defined(__APPLE__)
+ auto* daemon = new SignalDaemon(this);
+
+ connect(daemon, &SignalDaemon::InterruptReceived, this, &MainWindow::OnSignal);
+
+ InstallSignalHandler();
+#endif
+
if (boot_parameters)
m_pending_boot = std::move(boot_parameters);
diff --git a/Source/Core/DolphinQt2/MainWindow.h b/Source/Core/DolphinQt2/MainWindow.h
index cb0c26e772..741a9b46c3 100644
--- a/Source/Core/DolphinQt2/MainWindow.h
+++ b/Source/Core/DolphinQt2/MainWindow.h
@@ -138,6 +138,7 @@ private:
void OnBootGameCubeIPL(DiscIO::Region region);
void OnImportNANDBackup();
void OnConnectWiiRemote(int id);
+ void OnSignal();
void OnUpdateProgressDialog(QString label, int progress, int total);
diff --git a/Source/Core/DolphinQt2/QtUtils/SignalDaemon.cpp b/Source/Core/DolphinQt2/QtUtils/SignalDaemon.cpp
new file mode 100644
index 0000000000..546b03a252
--- /dev/null
+++ b/Source/Core/DolphinQt2/QtUtils/SignalDaemon.cpp
@@ -0,0 +1,55 @@
+// Copyright 2018 Dolphin Emulator Project
+// Licensed under GPLv2+
+// Refer to the license.txt file included.
+
+#include "DolphinQt2/QtUtils/SignalDaemon.h"
+
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <QSocketNotifier>
+
+int SignalDaemon::s_sigterm_fd[2];
+
+static constexpr char message[] =
+ "\nA signal was received. A second signal will force Dolphin to stop.\n";
+
+SignalDaemon::SignalDaemon(QObject* parent) : QObject(parent)
+{
+ if (socketpair(AF_UNIX, SOCK_STREAM, 0, s_sigterm_fd))
+ qFatal("Couldn't create TERM socketpair");
+
+ m_term = new QSocketNotifier(s_sigterm_fd[1], QSocketNotifier::Read, this);
+ connect(m_term, &QSocketNotifier::activated, this, &SignalDaemon::OnNotifierActivated);
+}
+
+SignalDaemon::~SignalDaemon()
+{
+ close(s_sigterm_fd[0]);
+ close(s_sigterm_fd[1]);
+}
+
+void SignalDaemon::OnNotifierActivated()
+{
+ m_term->setEnabled(false);
+
+ char tmp;
+ if (read(s_sigterm_fd[1], &tmp, sizeof(char)))
+ {
+ }
+
+ m_term->setEnabled(true);
+
+ emit InterruptReceived();
+}
+
+void SignalDaemon::HandleInterrupt(int)
+{
+ write(STDERR_FILENO, message, sizeof(message));
+
+ char a = 1;
+ if (write(s_sigterm_fd[0], &a, sizeof(a)))
+ {
+ }
+}
diff --git a/Source/Core/DolphinQt2/QtUtils/SignalDaemon.h b/Source/Core/DolphinQt2/QtUtils/SignalDaemon.h
new file mode 100644
index 0000000000..1c17f07e07
--- /dev/null
+++ b/Source/Core/DolphinQt2/QtUtils/SignalDaemon.h
@@ -0,0 +1,31 @@
+// Copyright 2018 Dolphin Emulator Project
+// Licensed under GPLv2+
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include <QObject>
+
+class QSocketNotifier;
+
+// Loosely based on https://doc.qt.io/qt-5.9/unix-signals.html
+class SignalDaemon : public QObject
+{
+ Q_OBJECT
+
+public:
+ explicit SignalDaemon(QObject* parent);
+ ~SignalDaemon();
+
+ static void HandleInterrupt(int);
+
+signals:
+ void InterruptReceived();
+
+private:
+ void OnNotifierActivated();
+
+ static int s_sigterm_fd[2];
+
+ QSocketNotifier* m_term;
+};