diff --git a/CMakeLists.txt b/CMakeLists.txt index 0935b1f4a8..c0d517c5e4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1066,6 +1066,8 @@ set(LIBNETDATA_FILES src/libnetdata/os/file_lock.h src/libnetdata/os/mmap_limit.c src/libnetdata/os/mmap_limit.h + src/libnetdata/signals/signals.c + src/libnetdata/signals/signals.h ) list(APPEND LIBNETDATA_FILES ${INICFG_FILES}) @@ -1171,8 +1173,8 @@ set(DAEMON_FILES src/daemon/environment.c src/daemon/win_system-info.c src/daemon/win_system-info.h - src/daemon/signals.c - src/daemon/signals.h + src/daemon/signal-handler.c + src/daemon/signal-handler.h src/daemon/service.c src/daemon/daemon-shutdown-watcher.c src/daemon/daemon-shutdown-watcher.h diff --git a/src/daemon/common.h b/src/daemon/common.h index 3138c2add3..16c466b3aa 100644 --- a/src/daemon/common.h +++ b/src/daemon/common.h @@ -70,7 +70,7 @@ extern "C" { #include "daemon.h" #include "main.h" #include "static_threads.h" -#include "signals.h" +#include "signal-handler.h" #include "commands.h" #include "pipename.h" #include "analytics.h" diff --git a/src/daemon/daemon-shutdown.c b/src/daemon/daemon-shutdown.c index 54f101ae61..bd44e71545 100644 --- a/src/daemon/daemon-shutdown.c +++ b/src/daemon/daemon-shutdown.c @@ -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)) 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++) rrdeng_quiesce(multidb_ctx[tier]); diff --git a/src/daemon/daemon-status-file.c b/src/daemon/daemon-status-file.c index c727fdd54a..f7a54f7845 100644 --- a/src/daemon/daemon-status-file.c +++ b/src/daemon/daemon-status-file.c @@ -819,7 +819,7 @@ void daemon_status_file_check_crash(void) { bool post_crash_report = false; bool disable_crash_report = false; bool dump_json = true; - const char *msg, *cause; + const char *msg = "", *cause = ""; switch(last_session_status.status) { default: case DAEMON_STATUS_NONE: @@ -1017,12 +1017,13 @@ void daemon_status_file_check_crash(void) { daemon_status_file_startup_step("startup(post status file)"); - struct post_status_file_thread_data *d = calloc(1, sizeof(*d)); - d->cause = cause; - d->msg = msg; - d->status = &last_session_status; - d->priority = pri.post; - post_status_file(d); + struct post_status_file_thread_data d = { + .cause = cause, + .msg = msg, + .status = &last_session_status, + .priority = pri.post, + }; + post_status_file(&d); // 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. diff --git a/src/daemon/signals.c b/src/daemon/signal-handler.c similarity index 90% rename from src/daemon/signals.c rename to src/daemon/signal-handler.c index 748ebeb16a..eb173153bd 100644 --- a/src/daemon/signals.c +++ b/src/daemon/signal-handler.c @@ -80,25 +80,6 @@ static void signal_handler(int signo) { __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. // All other signals remain masked. static void posix_unmask_my_signals(void) { @@ -113,7 +94,7 @@ static void posix_unmask_my_signals(void) { } void nd_initialize_signals(void) { - posix_signals_default_mask(); + signals_block_all_except_deadly(); // Catch signals which we want to use struct sigaction sa; diff --git a/src/daemon/signals.h b/src/daemon/signal-handler.h similarity index 54% rename from src/daemon/signals.h rename to src/daemon/signal-handler.h index 897b2b7f0c..927c2478c7 100644 --- a/src/daemon/signals.h +++ b/src/daemon/signal-handler.h @@ -1,9 +1,9 @@ // SPDX-License-Identifier: GPL-3.0-or-later -#ifndef NETDATA_SIGNALS_H -#define NETDATA_SIGNALS_H 1 +#ifndef NETDATA_SIGNAL_HANDLER_H +#define NETDATA_SIGNAL_HANDLER_H 1 void nd_initialize_signals(void); void nd_process_signals(void) NORETURN; -#endif //NETDATA_SIGNALS_H +#endif //NETDATA_SIGNAL_HANDLER_H diff --git a/src/database/engine/rrdengineapi.c b/src/database/engine/rrdengineapi.c index 795b47394e..4778697580 100755 --- a/src/database/engine/rrdengineapi.c +++ b/src/database/engine/rrdengineapi.c @@ -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); 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"); handle->now_s += handle->dt_s; diff --git a/src/libnetdata/libnetdata.h b/src/libnetdata/libnetdata.h index 8a8c9e2323..ab1dc868d1 100644 --- a/src/libnetdata/libnetdata.h +++ b/src/libnetdata/libnetdata.h @@ -8,6 +8,7 @@ extern "C" { # endif #include "common.h" +#include "signals/signals.h" #include "memory/alignment.h" #include "memory/nd-mallocz.h" #include "memory/nd-mmap.h" diff --git a/src/libnetdata/log/nd_log.c b/src/libnetdata/log/nd_log.c index e16fa7446a..2f73b2d33b 100644 --- a/src/libnetdata/log/nd_log.c +++ b/src/libnetdata/log/nd_log.c @@ -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); #ifdef NETDATA_INTERNAL_CHECKS - // abort(); + abort(); #endif if(nd_log.fatal_final_cb) diff --git a/src/libnetdata/signals/signals.c b/src/libnetdata/signals/signals.c new file mode 100644 index 0000000000..26187dded3 --- /dev/null +++ b/src/libnetdata/signals/signals.c @@ -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)); +} diff --git a/src/libnetdata/signals/signals.h b/src/libnetdata/signals/signals.h new file mode 100644 index 0000000000..9393aa88fd --- /dev/null +++ b/src/libnetdata/signals/signals.h @@ -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 diff --git a/src/libnetdata/spawn_server/spawn_server_libuv.c b/src/libnetdata/spawn_server/spawn_server_libuv.c index 49eba349da..3a800cbb9a 100644 --- a/src/libnetdata/spawn_server/spawn_server_libuv.c +++ b/src/libnetdata/spawn_server/spawn_server_libuv.c @@ -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) { SPAWN_SERVER *server = (SPAWN_SERVER *)arg; nd_log(NDLS_COLLECTORS, NDLP_ERR, @@ -114,7 +105,7 @@ static void server_thread(void *arg) { // this thread needs to process SIGCHLD (by libuv) // otherwise the on_exit() callback is never run - posix_unmask_sigchld_on_thread(); + signals_unblock_one(SIGCHLD); // run the event loop uv_run(server->loop, UV_RUN_DEFAULT); diff --git a/src/libnetdata/spawn_server/spawn_server_nofork.c b/src/libnetdata/spawn_server/spawn_server_nofork.c index 93607f8670..a71e563239 100644 --- a/src/libnetdata/spawn_server/spawn_server_nofork.c +++ b/src/libnetdata/spawn_server/spawn_server_nofork.c @@ -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) { int pipe_fd = server->pipe[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 struct sigaction sa;