MainNoGUI: Shut down cleanly on shutdown signal

This is the same as PR #3991, but for MainNoGUI.

nogui/headless will shut down cleanly on SIGINT and SIGTERM, just like
it would when closing the render window.

The default signal handler will be restored after a first shutdown
signal so a second signal will exit Dolphin forcefully.
This commit is contained in:
Léo Lam 2016-09-24 21:17:34 +02:00
parent c59b7050d9
commit 3cbf3bae97

View File

@ -6,12 +6,14 @@
#include <cstdio> #include <cstdio>
#include <cstring> #include <cstring>
#include <getopt.h> #include <getopt.h>
#include <signal.h>
#include <string> #include <string>
#include <thread> #include <thread>
#include <unistd.h> #include <unistd.h>
#include "Common/CommonTypes.h" #include "Common/CommonTypes.h"
#include "Common/Event.h" #include "Common/Event.h"
#include "Common/Flag.h"
#include "Common/Logging/LogManager.h" #include "Common/Logging/LogManager.h"
#include "Common/MsgHandler.h" #include "Common/MsgHandler.h"
@ -31,7 +33,16 @@
static bool rendererHasFocus = true; static bool rendererHasFocus = true;
static bool rendererIsFullscreen = false; static bool rendererIsFullscreen = false;
static bool running = true; static Common::Flag s_running{true};
static void signal_handler(int)
{
const char message[] = "A signal was received. A second signal will force Dolphin to stop.\n";
if (write(STDERR_FILENO, message, sizeof(message)) < 0)
{
}
s_running.Clear();
}
class Platform class Platform
{ {
@ -40,7 +51,7 @@ public:
virtual void SetTitle(const std::string& title) {} virtual void SetTitle(const std::string& title) {}
virtual void MainLoop() virtual void MainLoop()
{ {
while (running) while (s_running.IsSet())
{ {
Core::HostDispatchJobs(); Core::HostDispatchJobs();
std::this_thread::sleep_for(std::chrono::milliseconds(100)); std::this_thread::sleep_for(std::chrono::milliseconds(100));
@ -64,7 +75,7 @@ void Host_Message(int Id)
{ {
if (Id == WM_USER_STOP) if (Id == WM_USER_STOP)
{ {
running = false; s_running.Clear();
updateMainFrameEvent.Set(); updateMainFrameEvent.Set();
} }
} }
@ -209,7 +220,7 @@ class PlatformX11 : public Platform
} }
// The actual loop // The actual loop
while (running) while (s_running.IsSet())
{ {
XEvent event; XEvent event;
KeySym key; KeySym key;
@ -275,7 +286,7 @@ class PlatformX11 : public Platform
break; break;
case ClientMessage: case ClientMessage:
if ((unsigned long)event.xclient.data.l[0] == XInternAtom(dpy, "WM_DELETE_WINDOW", False)) if ((unsigned long)event.xclient.data.l[0] == XInternAtom(dpy, "WM_DELETE_WINDOW", False))
running = false; s_running.Clear();
break; break;
} }
} }
@ -366,6 +377,14 @@ int main(int argc, char* argv[])
platform->Init(); platform->Init();
// Shut down cleanly on SIGINT and SIGTERM
struct sigaction sa;
sa.sa_handler = signal_handler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESETHAND;
sigaction(SIGINT, &sa, nullptr);
sigaction(SIGTERM, &sa, nullptr);
DolphinAnalytics::Instance()->ReportDolphinStart("nogui"); DolphinAnalytics::Instance()->ReportDolphinStart("nogui");
if (!BootManager::BootCore(argv[optind])) if (!BootManager::BootCore(argv[optind]))
@ -374,13 +393,13 @@ int main(int argc, char* argv[])
return 1; return 1;
} }
while (!Core::IsRunning() && running) while (!Core::IsRunning() && s_running.IsSet())
{ {
Core::HostDispatchJobs(); Core::HostDispatchJobs();
updateMainFrameEvent.Wait(); updateMainFrameEvent.Wait();
} }
if (running) if (s_running.IsSet())
platform->MainLoop(); platform->MainLoop();
Core::Stop(); Core::Stop();