0
0
Fork 0
mirror of https://github.com/netdata/netdata.git synced 2025-04-23 21:10:22 +00:00

block all signals before spawning any threads ()

* block all signals before spawning any threads

* fix header

* fix header again

* uniform signals masking

* fix log
This commit is contained in:
Costa Tsaousis 2025-03-04 21:50:17 +00:00 committed by GitHub
parent e30c3a52d1
commit 0c5d34d41a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
13 changed files with 81 additions and 57 deletions

View file

@ -1066,6 +1066,8 @@ set(LIBNETDATA_FILES
src/libnetdata/os/file_lock.h src/libnetdata/os/file_lock.h
src/libnetdata/os/mmap_limit.c src/libnetdata/os/mmap_limit.c
src/libnetdata/os/mmap_limit.h src/libnetdata/os/mmap_limit.h
src/libnetdata/signals/signals.c
src/libnetdata/signals/signals.h
) )
list(APPEND LIBNETDATA_FILES ${INICFG_FILES}) list(APPEND LIBNETDATA_FILES ${INICFG_FILES})
@ -1171,8 +1173,8 @@ set(DAEMON_FILES
src/daemon/environment.c src/daemon/environment.c
src/daemon/win_system-info.c src/daemon/win_system-info.c
src/daemon/win_system-info.h src/daemon/win_system-info.h
src/daemon/signals.c src/daemon/signal-handler.c
src/daemon/signals.h src/daemon/signal-handler.h
src/daemon/service.c src/daemon/service.c
src/daemon/daemon-shutdown-watcher.c src/daemon/daemon-shutdown-watcher.c
src/daemon/daemon-shutdown-watcher.h src/daemon/daemon-shutdown-watcher.h

View file

@ -70,7 +70,7 @@ extern "C" {
#include "daemon.h" #include "daemon.h"
#include "main.h" #include "main.h"
#include "static_threads.h" #include "static_threads.h"
#include "signals.h" #include "signal-handler.h"
#include "commands.h" #include "commands.h"
#include "pipename.h" #include "pipename.h"
#include "analytics.h" #include "analytics.h"

View file

@ -106,7 +106,7 @@ static void rrdeng_flush_everything_and_wait(bool wait_flush, bool wait_collecto
if(!pgc_hot_and_dirty_entries(main_cache)) if(!pgc_hot_and_dirty_entries(main_cache))
return; return;
nd_log(NDLS_DAEMON, NDLP_INFO, "Flushing DBENGINE dirty pages..."); nd_log(NDLS_DAEMON, NDLP_INFO, "Flushing DBENGINE hot & dirty pages...");
for (size_t tier = 0; tier < nd_profile.storage_tiers; tier++) for (size_t tier = 0; tier < nd_profile.storage_tiers; tier++)
rrdeng_quiesce(multidb_ctx[tier]); rrdeng_quiesce(multidb_ctx[tier]);

View file

@ -819,7 +819,7 @@ void daemon_status_file_check_crash(void) {
bool post_crash_report = false; bool post_crash_report = false;
bool disable_crash_report = false; bool disable_crash_report = false;
bool dump_json = true; bool dump_json = true;
const char *msg, *cause; const char *msg = "", *cause = "";
switch(last_session_status.status) { switch(last_session_status.status) {
default: default:
case DAEMON_STATUS_NONE: case DAEMON_STATUS_NONE:
@ -1017,12 +1017,13 @@ void daemon_status_file_check_crash(void) {
daemon_status_file_startup_step("startup(post status file)"); daemon_status_file_startup_step("startup(post status file)");
struct post_status_file_thread_data *d = calloc(1, sizeof(*d)); struct post_status_file_thread_data d = {
d->cause = cause; .cause = cause,
d->msg = msg; .msg = msg,
d->status = &last_session_status; .status = &last_session_status,
d->priority = pri.post; .priority = pri.post,
post_status_file(d); };
post_status_file(&d);
// MacOS crashes when starting under launchctl, when we create a thread to post the status file, // MacOS crashes when starting under launchctl, when we create a thread to post the status file,
// so we post the status file synchronously, with a timeout of 10 seconds. // so we post the status file synchronously, with a timeout of 10 seconds.

View file

@ -80,25 +80,6 @@ static void signal_handler(int signo) {
__atomic_sub_fetch(&recurse, 1, __ATOMIC_RELAXED); __atomic_sub_fetch(&recurse, 1, __ATOMIC_RELAXED);
} }
// Mask all signals, to ensure they will only be unmasked at the threads that can handle them.
// This means that all third party libraries (including libuv) cannot use signals anymore.
// The signals they are interested must be unblocked at their corresponding event loops.
static void posix_signals_default_mask(void) {
sigset_t sigset;
sigfillset(&sigset);
// Don't mask fatal signals - we want these to be handled in any thread
sigdelset(&sigset, SIGBUS);
sigdelset(&sigset, SIGSEGV);
sigdelset(&sigset, SIGFPE);
sigdelset(&sigset, SIGILL);
sigdelset(&sigset, SIGABRT);
if(pthread_sigmask(SIG_BLOCK, &sigset, NULL) != 0)
netdata_log_error("SIGNAL: cannot apply the default mask for signals");
}
// Unmask all signals the netdata main signal handler uses. // Unmask all signals the netdata main signal handler uses.
// All other signals remain masked. // All other signals remain masked.
static void posix_unmask_my_signals(void) { static void posix_unmask_my_signals(void) {
@ -113,7 +94,7 @@ static void posix_unmask_my_signals(void) {
} }
void nd_initialize_signals(void) { void nd_initialize_signals(void) {
posix_signals_default_mask(); signals_block_all_except_deadly();
// Catch signals which we want to use // Catch signals which we want to use
struct sigaction sa; struct sigaction sa;

View file

@ -1,9 +1,9 @@
// SPDX-License-Identifier: GPL-3.0-or-later // SPDX-License-Identifier: GPL-3.0-or-later
#ifndef NETDATA_SIGNALS_H #ifndef NETDATA_SIGNAL_HANDLER_H
#define NETDATA_SIGNALS_H 1 #define NETDATA_SIGNAL_HANDLER_H 1
void nd_initialize_signals(void); void nd_initialize_signals(void);
void nd_process_signals(void) NORETURN; void nd_process_signals(void) NORETURN;
#endif //NETDATA_SIGNALS_H #endif //NETDATA_SIGNAL_HANDLER_H

View file

@ -901,7 +901,7 @@ ALWAYS_INLINE_HOT STORAGE_POINT rrdeng_load_metric_next(struct storage_engine_qu
pgdc_get_next_point(&handle->pgdc, handle->position, &sp); pgdc_get_next_point(&handle->pgdc, handle->position, &sp);
prepare_for_next_iteration: prepare_for_next_iteration:
internal_fatal(sp.end_time_s < seqh->start_time_s, "DBENGINE: this point is too old for this query"); // internal_fatal(sp.end_time_s < seqh->start_time_s, "DBENGINE: this point is too old for this query");
internal_fatal(sp.end_time_s < handle->now_s, "DBENGINE: this point is too old for this point in time"); internal_fatal(sp.end_time_s < handle->now_s, "DBENGINE: this point is too old for this point in time");
handle->now_s += handle->dt_s; handle->now_s += handle->dt_s;

View file

@ -8,6 +8,7 @@ extern "C" {
# endif # endif
#include "common.h" #include "common.h"
#include "signals/signals.h"
#include "memory/alignment.h" #include "memory/alignment.h"
#include "memory/nd-mallocz.h" #include "memory/nd-mallocz.h"
#include "memory/nd-mmap.h" #include "memory/nd-mmap.h"

View file

@ -518,7 +518,7 @@ void netdata_logger_fatal(const char *file, const char *function, const unsigned
snprintfz(action_result, 60, "%s:%s:%s", program_name, tag_to_send, function); snprintfz(action_result, 60, "%s:%s:%s", program_name, tag_to_send, function);
#ifdef NETDATA_INTERNAL_CHECKS #ifdef NETDATA_INTERNAL_CHECKS
// abort(); abort();
#endif #endif
if(nd_log.fatal_final_cb) if(nd_log.fatal_final_cb)

View file

@ -0,0 +1,42 @@
// SPDX-License-Identifier: GPL-3.0-or-later
#include "../libnetdata.h"
void signals_block_all(void) {
sigset_t sigset;
sigfillset(&sigset);
if(pthread_sigmask(SIG_BLOCK, &sigset, NULL) != 0)
nd_log(NDLS_DAEMON, NDLP_ERR,
"SIGNALS: cannot apply the default mask for signals");
}
void signals_unblock_one(int signo) {
sigset_t sigset;
sigemptyset(&sigset); // Initialize the signal set to empty
sigaddset(&sigset, signo); // Add our signal to the set
if(pthread_sigmask(SIG_UNBLOCK, &sigset, NULL) != 0)
nd_log(NDLS_COLLECTORS, NDLP_ERR,
"SIGNALS: cannot unmask signal %d", signo);
}
void signals_unblock(int signals[], size_t count) {
sigset_t sigset;
sigemptyset(&sigset); // Initialize the signal set to empty
// Add each signal from the array to the signal set
for (size_t i = 0; i < count; i++)
sigaddset(&sigset, signals[i]);
// Unblock all signals in the set
if (pthread_sigmask(SIG_UNBLOCK, &sigset, NULL) != 0)
nd_log(NDLS_COLLECTORS, NDLP_ERR, "SIGNALS: cannot unmask signals");
}
void signals_block_all_except_deadly(void) {
signals_block_all();
int deadly_signals[] = {SIGBUS, SIGSEGV, SIGFPE, SIGILL, SIGABRT};
signals_unblock(deadly_signals, _countof(deadly_signals));
}

View file

@ -0,0 +1,14 @@
// SPDX-License-Identifier: GPL-3.0-or-later
#ifndef NETDATA_SIGNALS_H
#define NETDATA_SIGNALS_H
#include "../common.h"
void signals_block_all_except_deadly(void);
void signals_block_all(void);
void signals_unblock_one(int signo);
void signals_unblock(int signals[], size_t count);
#endif //NETDATA_SIGNALS_H

View file

@ -98,15 +98,6 @@ int uv_errno_to_errno(int uv_err) {
} }
} }
static void posix_unmask_sigchld_on_thread(void) {
sigset_t sigset;
sigemptyset(&sigset); // Initialize the signal set to empty
sigaddset(&sigset, SIGCHLD); // Add SIGCHLD to the set
if(pthread_sigmask(SIG_UNBLOCK, &sigset, NULL) != 0)
netdata_log_error("SPAWN SERVER: cannot unmask SIGCHLD");
}
static void server_thread(void *arg) { static void server_thread(void *arg) {
SPAWN_SERVER *server = (SPAWN_SERVER *)arg; SPAWN_SERVER *server = (SPAWN_SERVER *)arg;
nd_log(NDLS_COLLECTORS, NDLP_ERR, nd_log(NDLS_COLLECTORS, NDLP_ERR,
@ -114,7 +105,7 @@ static void server_thread(void *arg) {
// this thread needs to process SIGCHLD (by libuv) // this thread needs to process SIGCHLD (by libuv)
// otherwise the on_exit() callback is never run // otherwise the on_exit() callback is never run
posix_unmask_sigchld_on_thread(); signals_unblock_one(SIGCHLD);
// run the event loop // run the event loop
uv_run(server->loop, UV_RUN_DEFAULT); uv_run(server->loop, UV_RUN_DEFAULT);

View file

@ -830,21 +830,13 @@ static void spawn_server_process_sigchld(void) {
} }
} }
static void posix_unmask_sigchld_on_thread(void) {
sigset_t sigset;
sigemptyset(&sigset); // Initialize the signal set to empty
sigaddset(&sigset, SIGCHLD); // Add SIGCHLD to the set
if(pthread_sigmask(SIG_UNBLOCK, &sigset, NULL) != 0)
nd_log(NDLS_COLLECTORS, NDLP_ERR,
"SPAWN SERVER: cannot unmask SIGCHLD");
}
static int spawn_server_event_loop(SPAWN_SERVER *server) { static int spawn_server_event_loop(SPAWN_SERVER *server) {
int pipe_fd = server->pipe[1]; int pipe_fd = server->pipe[1];
close(server->pipe[0]); server->pipe[0] = -1; close(server->pipe[0]); server->pipe[0] = -1;
posix_unmask_sigchld_on_thread(); signals_block_all();
int wanted_signals[] = {SIGTERM, SIGCHLD};
signals_unblock(wanted_signals, _countof(wanted_signals));
// Set up the signal handler for SIGCHLD and SIGTERM // Set up the signal handler for SIGCHLD and SIGTERM
struct sigaction sa; struct sigaction sa;