From a5145916503cf295cccb514e4d2ffc589238462f Mon Sep 17 00:00:00 2001 From: Lion Kortlepel Date: Thu, 9 Sep 2021 11:37:56 +0300 Subject: [PATCH] Main: Add Ctrl+C handler for windows --- CMakeLists.txt | 3 +- Changelog.md | 4 +++ include/SignalHandling.h | 68 ++++++++++++++++++++++++++++++++++++++++ src/main.cpp | 43 ++++++------------------- 4 files changed, 83 insertions(+), 35 deletions(-) create mode 100644 include/SignalHandling.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 4f9f672..a072d12 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -81,7 +81,8 @@ add_executable(BeamMP-Server include/Http.h src/Http.cpp include/TSentry.h src/TSentry.cpp include/TPPSMonitor.h src/TPPSMonitor.cpp - include/TNetwork.h src/TNetwork.cpp) + include/TNetwork.h src/TNetwork.cpp + include/SignalHandling.h) target_compile_definitions(BeamMP-Server PRIVATE SECRET_SENTRY_URL="${BEAMMP_SECRET_SENTRY_URL}") diff --git a/Changelog.md b/Changelog.md index 7a5832d..b4cd153 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,3 +1,7 @@ +# v2.3.2 + +- ADDED Ctrl+C and closing the console causing a graceful shutdown + # v2.3.1 - CHANGED join/sync timeout to 20 minutes, players wont drop if loading takes >5 mins diff --git a/include/SignalHandling.h b/include/SignalHandling.h new file mode 100644 index 0000000..8f3dc93 --- /dev/null +++ b/include/SignalHandling.h @@ -0,0 +1,68 @@ +#pragma once + +#include "Common.h" + +#ifdef __unix +#include +static void UnixSignalHandler(int sig) { + switch (sig) { + case SIGPIPE: + warn("ignoring SIGPIPE"); + break; + case SIGTERM: + info("gracefully shutting down via SIGTERM"); + Application::GracefullyShutdown(); + break; + case SIGINT: + info("gracefully shutting down via SIGINT"); + Application::GracefullyShutdown(); + break; + default: + debug("unhandled signal: " + std::to_string(sig)); + break; + } +} +#endif // __unix + +#ifdef WIN32 +#include +// return TRUE if handled, FALSE if not +BOOL WINAPI Win32CtrlC_Handler(DWORD CtrlType) { + switch (CtrlType) { + case CTRL_C_EVENT: + info("gracefully shutting down via CTRL+C"); + Application::GracefullyShutdown(); + return TRUE; + case CTRL_BREAK_EVENT: + info("gracefully shutting down via CTRL+BREAK"); + Application::GracefullyShutdown(); + return TRUE; + case CTRL_CLOSE_EVENT: + info("gracefully shutting down via close"); + Application::GracefullyShutdown(); + return TRUE; + } + // we dont care for any others like CTRL_LOGOFF_EVENT and CTRL_SHUTDOWN_EVENT + return FALSE; +} +#endif // WIN32 + +// clang-format off +static void SetupSignalHandlers() { + // signal handlers for unix + #ifdef __unix + trace("registering handlers for SIGINT, SIGTERM, SIGPIPE"); + signal(SIGPIPE, UnixSignalHandler); + signal(SIGTERM, UnixSignalHandler); + #ifndef DEBUG + signal(SIGINT, UnixSignalHandler); + #endif // DEBUG + #endif // __unix + + // signal handlers for win32 + #ifdef WIN32 + trace("registering handlers for CTRL_*_EVENTs"); + SetConsoleCtrlHandler(Win32CtrlC_Handler, TRUE); + #endif // WIN32 +} +// clang-format on diff --git a/src/main.cpp b/src/main.cpp index 5e0aeaa..53d4a4c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -10,49 +10,20 @@ #include "TPPSMonitor.h" #include "TResourceManager.h" #include "TServer.h" +#include "SignalHandling.h" +#include #include -#ifdef __unix -#include - -void UnixSignalHandler(int sig) { - switch (sig) { - case SIGPIPE: - warn("ignoring SIGPIPE"); - break; - case SIGTERM: - info("gracefully shutting down via SIGTERM"); - Application::GracefullyShutdown(); - break; - case SIGINT: - info("gracefully shutting down via SIGINT"); - Application::GracefullyShutdown(); - break; - default: - debug("unhandled signal: " + std::to_string(sig)); - break; - } -} -#endif // __unix - // this is provided by the build system, leave empty for source builds // global, yes, this is ugly, no, it cant be done another way TSentry Sentry {}; -#include - int main(int argc, char** argv) try { -#ifdef __unix - trace("registering handlers for SIGINT, SIGTERM, SIGPIPE"); - signal(SIGPIPE, UnixSignalHandler); - signal(SIGTERM, UnixSignalHandler); -#ifndef DEBUG - signal(SIGINT, UnixSignalHandler); -#endif // DEBUG -#endif // __unix setlocale(LC_ALL, "C"); + SetupSignalHandlers(); + bool Shutdown = false; Application::RegisterShutdownHandler([&Shutdown] { Shutdown = true; }); @@ -61,7 +32,10 @@ int main(int argc, char** argv) try { if (Config.Failed()) { info("Closing in 10 seconds"); - std::this_thread::sleep_for(std::chrono::seconds(10)); + // loop to make it possible to ctrl+c instead + for (size_t i = 0; i < 20; ++i) { + std::this_thread::sleep_for(std::chrono::milliseconds(500)); + } return 1; } @@ -88,3 +62,4 @@ int main(int argc, char** argv) try { error(e.what()); Sentry.LogException(e, _file_basename, _line); } +