Skip to content

Commit

Permalink
Shut down the server orderly on termination signals
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
andrey-utkin committed Dec 11, 2024
1 parent 252fd3e commit 5f28d26
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 5 deletions.
1 change: 1 addition & 0 deletions debian/bluecherry.service
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
7 changes: 7 additions & 0 deletions server/bc-server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -1810,6 +1816,7 @@ int main(int argc, char **argv)
}

#ifdef V3_LICENSING
v3license_server::stopThread();
pthread_join(v3license_thread, NULL);
#endif /* V3_LICENSING */

Expand Down
27 changes: 22 additions & 5 deletions server/signals.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include <assert.h>

#include "bt.h"

Expand All @@ -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;
Expand All @@ -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;
}

Expand All @@ -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);
}

0 comments on commit 5f28d26

Please sign in to comment.