diff options
| -rw-r--r-- | src/yuzu/main.cpp | 60 | ||||
| -rw-r--r-- | src/yuzu/main.h | 11 |
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 | ||
| 468 | void GMainWindow::RegisterMetaTypes() { | 482 | void 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 | |||
| 1370 | std::array<int, 3> GMainWindow::sig_interrupt_fds{0, 0, 0}; | ||
| 1371 | |||
| 1372 | void 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 | |||
| 1392 | void 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 | |||
| 1404 | void 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 | ||
| 1357 | void GMainWindow::PreventOSSleep() { | 1417 | void 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 | |||
| 166 | public slots: | 168 | public 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 | |||
| 254 | private slots: | 262 | private 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 | ||