summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/yuzu/main.cpp60
-rw-r--r--src/yuzu/main.h11
2 files changed, 71 insertions, 0 deletions
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index 84fccab34..ef91ef19c 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -8,6 +8,10 @@
8#ifdef __APPLE__ 8#ifdef __APPLE__
9#include <unistd.h> // for chdir 9#include <unistd.h> // for chdir
10#endif 10#endif
11#ifdef __linux__
12#include <csignal>
13#include <sys/socket.h>
14#endif
11 15
12// VFS includes must be before glad as they will conflict with Windows file api, which uses defines. 16// VFS includes must be before glad as they will conflict with Windows file api, which uses defines.
13#include "applets/qt_controller.h" 17#include "applets/qt_controller.h"
@@ -259,6 +263,10 @@ GMainWindow::GMainWindow(bool has_broken_vulkan)
259 config{std::make_unique<Config>(*system)}, 263 config{std::make_unique<Config>(*system)},
260 vfs{std::make_shared<FileSys::RealVfsFilesystem>()}, 264 vfs{std::make_shared<FileSys::RealVfsFilesystem>()},
261 provider{std::make_unique<FileSys::ManualContentProvider>()} { 265 provider{std::make_unique<FileSys::ManualContentProvider>()} {
266#ifdef __linux__
267 SetupSigInterrupts();
268#endif
269
262 Common::Log::Initialize(); 270 Common::Log::Initialize();
263 LoadTranslation(); 271 LoadTranslation();
264 272
@@ -462,7 +470,13 @@ GMainWindow::~GMainWindow() {
462 if (render_window->parent() == nullptr) { 470 if (render_window->parent() == nullptr) {
463 delete render_window; 471 delete render_window;
464 } 472 }
473
465 system->GetRoomNetwork().Shutdown(); 474 system->GetRoomNetwork().Shutdown();
475
476#ifdef __linux__
477 ::close(sig_interrupt_fds[0]);
478 ::close(sig_interrupt_fds[1]);
479#endif
466} 480}
467 481
468void GMainWindow::RegisterMetaTypes() { 482void GMainWindow::RegisterMetaTypes() {
@@ -1352,6 +1366,52 @@ static void ReleaseWakeLockLinux(QDBusObjectPath lock) {
1352 QString::fromLatin1("org.freedesktop.portal.Request")); 1366 QString::fromLatin1("org.freedesktop.portal.Request"));
1353 unlocker.call(QString::fromLatin1("Close")); 1367 unlocker.call(QString::fromLatin1("Close"));
1354} 1368}
1369
1370std::array<int, 3> GMainWindow::sig_interrupt_fds{0, 0, 0};
1371
1372void GMainWindow::SetupSigInterrupts() {
1373 if (sig_interrupt_fds[2] == 1) {
1374 return;
1375 }
1376 socketpair(AF_UNIX, SOCK_STREAM, 0, sig_interrupt_fds.data());
1377 sig_interrupt_fds[2] = 1;
1378
1379 struct sigaction sa;
1380 sa.sa_handler = &GMainWindow::HandleSigInterrupt;
1381 sigemptyset(&sa.sa_mask);
1382 sa.sa_flags = SA_RESETHAND;
1383 sigaction(SIGINT, &sa, nullptr);
1384 sigaction(SIGTERM, &sa, nullptr);
1385
1386 sig_interrupt_notifier = new QSocketNotifier(sig_interrupt_fds[1], QSocketNotifier::Read, this);
1387 connect(sig_interrupt_notifier, &QSocketNotifier::activated, this,
1388 &GMainWindow::OnSigInterruptNotifierActivated);
1389 connect(this, &GMainWindow::SigInterrupt, this, &GMainWindow::close);
1390}
1391
1392void GMainWindow::HandleSigInterrupt(int sig) {
1393 if (sig == SIGINT) {
1394 exit(1);
1395 }
1396
1397 // Calling into Qt directly from a signal handler is not safe,
1398 // so wake up a QSocketNotifier with this hacky write call instead.
1399 char a = 1;
1400 int ret = write(sig_interrupt_fds[0], &a, sizeof(a));
1401 (void)ret;
1402}
1403
1404void GMainWindow::OnSigInterruptNotifierActivated() {
1405 sig_interrupt_notifier->setEnabled(false);
1406
1407 char a;
1408 int ret = read(sig_interrupt_fds[1], &a, sizeof(a));
1409 (void)ret;
1410
1411 sig_interrupt_notifier->setEnabled(true);
1412
1413 emit SigInterrupt();
1414}
1355#endif // __linux__ 1415#endif // __linux__
1356 1416
1357void GMainWindow::PreventOSSleep() { 1417void GMainWindow::PreventOSSleep() {
diff --git a/src/yuzu/main.h b/src/yuzu/main.h
index de0d10974..509bb91df 100644
--- a/src/yuzu/main.h
+++ b/src/yuzu/main.h
@@ -163,6 +163,8 @@ signals:
163 void WebBrowserExtractOfflineRomFS(); 163 void WebBrowserExtractOfflineRomFS();
164 void WebBrowserClosed(Service::AM::Applets::WebExitReason exit_reason, std::string last_url); 164 void WebBrowserClosed(Service::AM::Applets::WebExitReason exit_reason, std::string last_url);
165 165
166 void SigInterrupt();
167
166public slots: 168public slots:
167 void OnLoadComplete(); 169 void OnLoadComplete();
168 void OnExecuteProgram(std::size_t program_index); 170 void OnExecuteProgram(std::size_t program_index);
@@ -251,6 +253,12 @@ private:
251 void RequestGameResume(); 253 void RequestGameResume();
252 void closeEvent(QCloseEvent* event) override; 254 void closeEvent(QCloseEvent* event) override;
253 255
256#ifdef __linux__
257 void SetupSigInterrupts();
258 static void HandleSigInterrupt(int);
259 void OnSigInterruptNotifierActivated();
260#endif
261
254private slots: 262private slots:
255 void OnStartGame(); 263 void OnStartGame();
256 void OnRestartGame(); 264 void OnRestartGame();
@@ -419,6 +427,9 @@ private:
419 bool is_tas_recording_dialog_active{}; 427 bool is_tas_recording_dialog_active{};
420 428
421#ifdef __linux__ 429#ifdef __linux__
430 QSocketNotifier* sig_interrupt_notifier;
431 static std::array<int, 3> sig_interrupt_fds;
432
422 QDBusObjectPath wake_lock{}; 433 QDBusObjectPath wake_lock{};
423#endif 434#endif
424 435