From 5f28d26d0dae561e815f8df1a0f8ef8a99fead0a Mon Sep 17 00:00:00 2001 From: Andriy Utkin Date: Wed, 11 Dec 2024 14:55:13 +0000 Subject: [PATCH] Shut down the server orderly on termination signals Previously, only abnormal (e.g. SIGABRT) or ignored (SIGCHLD) signals were actually handled. There was no handling for termination signals. This caused in-progress recording files to be left unreadable. --- debian/bluecherry.service | 1 + server/bc-server.cpp | 7 +++++++ server/signals.c | 27 ++++++++++++++++++++++----- 3 files changed, 30 insertions(+), 5 deletions(-) diff --git a/debian/bluecherry.service b/debian/bluecherry.service index ff71bbc14..111b8fb17 100644 --- a/debian/bluecherry.service +++ b/debian/bluecherry.service @@ -10,6 +10,7 @@ Group=bluecherry #ExecStart=/usr/bin/rr record -o /tmp/bluecherry.rr /usr/sbin/bc-server -s ExecStart=/usr/sbin/bc-server -s Restart=on-failure +TimeoutStopSec=30 [Install] WantedBy=multi-user.target diff --git a/server/bc-server.cpp b/server/bc-server.cpp index 9b0b7250c..319bc18e3 100644 --- a/server/bc-server.cpp +++ b/server/bc-server.cpp @@ -139,6 +139,8 @@ static bc_media_files g_media_files; #define BC_CLEANUP_RETRY_COUNT 5 #define BC_CLEANUP_RETRY_SEC 5 +extern const char *shutdown_reason; + void bc_status_component_begin(bc_status_component c) { if (status_component_active >= 0) { @@ -1747,6 +1749,10 @@ int main(int argc, char **argv) /* Main loop */ for (unsigned int loops = 0 ;; sleep(1), loops++) { + if (shutdown_reason) { + bc_log(Info, "Shutting down: %s", shutdown_reason); + break; + } /* Every 16 seconds until initialized, then every 4:16 minutes */ if ((!hwcard_ready && !(loops & 15)) || (hwcard_ready && !(loops & 255))) { bc_status_component_begin(STATUS_HWCARD_DETECT); @@ -1810,6 +1816,7 @@ int main(int argc, char **argv) } #ifdef V3_LICENSING + v3license_server::stopThread(); pthread_join(v3license_thread, NULL); #endif /* V3_LICENSING */ diff --git a/server/signals.c b/server/signals.c index d99aa8e8c..64ee60dbd 100644 --- a/server/signals.c +++ b/server/signals.c @@ -1,6 +1,7 @@ #include #include #include +#include #include "bt.h" @@ -12,6 +13,8 @@ static const char * const sig_name[] = { [SIGFPE] = "Floating point exception", }; +const char *shutdown_reason = NULL; + static void sighandler(int signum, siginfo_t *info, void *ctx) { (void)ctx; @@ -25,8 +28,14 @@ static void sighandler(int signum, siginfo_t *info, void *ctx) case SIGFPE: bt(sig_name[signum], info->si_addr); _exit(1); + + case SIGINT: + case SIGTERM: + case SIGQUIT: + case SIGHUP: + shutdown_reason = "Termination signal received"; + default: - /* SIGCHLD */ return; } @@ -35,15 +44,23 @@ static void sighandler(int signum, siginfo_t *info, void *ctx) void signals_setup() { - const int sig[] = { SIGCHLD, SIGFPE, SIGILL, SIGSEGV, SIGBUS, SIGABRT }; + int ret; + const int sig[] = { SIGFPE, SIGILL, SIGSEGV, SIGBUS, SIGABRT, SIGINT, SIGTERM, SIGQUIT, SIGHUP }; struct sigaction sa; memset(&sa, 0, sizeof(sa)); sa.sa_sigaction = sighandler; sa.sa_flags = SA_SIGINFO | SA_NOCLDWAIT; - for (unsigned int i = 0; i < sizeof(sig) / sizeof(sig[0]); i++) - sigaction(sig[i], &sa, NULL); + for (unsigned int i = 0; i < sizeof(sig) / sizeof(sig[0]); i++) { + ret = sigaction(sig[i], &sa, NULL); + assert(!ret); + } - signal(SIGPIPE, SIG_IGN); + // these signals are ignored: + sa.sa_sigaction = SIG_IGN; + ret = sigaction(SIGCHLD, &sa, NULL); + assert(!ret); + ret = sigaction(SIGPIPE, &sa, NULL); + assert(!ret); }