mirror of
https://github.com/netdata/netdata.git
synced 2025-04-13 17:19:11 +00:00
block all signals before spawning any threads (#19770)
* block all signals before spawning any threads * fix header * fix header again * uniform signals masking * fix log
This commit is contained in:
parent
e30c3a52d1
commit
0c5d34d41a
13 changed files with 81 additions and 57 deletions
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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]);
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
|
@ -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
|
|
@ -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;
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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)
|
||||
|
|
42
src/libnetdata/signals/signals.c
Normal file
42
src/libnetdata/signals/signals.c
Normal 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));
|
||||
}
|
14
src/libnetdata/signals/signals.h
Normal file
14
src/libnetdata/signals/signals.h
Normal 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
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Reference in a new issue