Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve dyncfg exit #15824

Merged
merged 2 commits into from
Aug 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
33 changes: 0 additions & 33 deletions daemon/static_threads.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,39 +5,6 @@

#include "common.h"

struct netdata_static_thread {
// the name of the thread as it should appear in the logs
char *name;

// the section of netdata.conf to check if this is enabled or not
char *config_section;

// the name of the config option to check if it is true or false
char *config_name;

// the current status of the thread
volatile sig_atomic_t enabled;

// internal use, to maintain a pointer to the created thread
netdata_thread_t *thread;

// an initialization function to run before spawning the thread
void (*init_routine) (void);

// the threaded worker
void *(*start_routine) (void *);

// the environment variable to create
char *env_name;

// global variable
bool *global_variable;
};

#define NETDATA_MAIN_THREAD_RUNNING CONFIG_BOOLEAN_YES
#define NETDATA_MAIN_THREAD_EXITING (CONFIG_BOOLEAN_YES + 1)
#define NETDATA_MAIN_THREAD_EXITED CONFIG_BOOLEAN_NO

extern const struct netdata_static_thread static_threads_common[];
extern const struct netdata_static_thread static_threads_linux[];
extern const struct netdata_static_thread static_threads_freebsd[];
Expand Down
64 changes: 52 additions & 12 deletions libnetdata/dyn_conf/dyn_conf.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,19 @@ struct deferred_cfg_send {
struct deferred_cfg_send *next;
};

bool dyncfg_shutdown = false;
struct deferred_cfg_send *deferred_configs = NULL;
pthread_mutex_t deferred_configs_lock = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t deferred_configs_cond = PTHREAD_COND_INITIALIZER;

static void deferred_config_free(struct deferred_cfg_send *dcs)
{
freez(dcs->plugin_name);
freez(dcs->module_name);
freez(dcs->job_name);
freez(dcs);
}

static void deferred_config_push_back(const char *plugin_name, const char *module_name, const char *job_name)
{
struct deferred_cfg_send *deferred = callocz(1, sizeof(struct deferred_cfg_send));
Expand All @@ -34,6 +43,11 @@ static void deferred_config_push_back(const char *plugin_name, const char *modul
deferred->job_name = strdupz(job_name);
}
pthread_mutex_lock(&deferred_configs_lock);
if (dyncfg_shutdown) {
pthread_mutex_unlock(&deferred_configs_lock);
deferred_config_free(deferred);
return;
}
struct deferred_cfg_send *last = deferred_configs;
if (last == NULL)
deferred_configs = deferred;
Expand All @@ -46,25 +60,29 @@ static void deferred_config_push_back(const char *plugin_name, const char *modul
pthread_mutex_unlock(&deferred_configs_lock);
}

static struct deferred_cfg_send *deferred_config_pop()
static void deferred_configs_unlock()
{
dyncfg_shutdown = true;
// if we get cancelled in pthread_cond_wait
// we will arrive at cancelled cleanup handler
// with mutex locked we need to unlock it
pthread_mutex_unlock(&deferred_configs_lock);
}

static struct deferred_cfg_send *deferred_config_pop(void *ptr)
{
pthread_mutex_lock(&deferred_configs_lock);
while (deferred_configs == NULL)
while (deferred_configs == NULL) {
netdata_thread_cleanup_push(deferred_configs_unlock, ptr);
pthread_cond_wait(&deferred_configs_cond, &deferred_configs_lock);
netdata_thread_cleanup_pop(0);
}
struct deferred_cfg_send *deferred = deferred_configs;
deferred_configs = deferred_configs->next;
pthread_mutex_unlock(&deferred_configs_lock);
return deferred;
}

static void deferred_config_free(struct deferred_cfg_send *dcs)
{
freez(dcs->plugin_name);
freez(dcs->module_name);
freez(dcs->job_name);
freez(dcs);
}

static int _get_list_of_plugins_json_cb(const DICTIONARY_ITEM *item, void *entry, void *data)
{
UNUSED(item);
Expand Down Expand Up @@ -870,10 +888,30 @@ int dyn_conf_init(void)
return 0;
}

void *dyncfg_main(void *in)
static void dyncfg_cleanup(void *ptr) {
struct netdata_static_thread *static_thread = (struct netdata_static_thread *) ptr;
static_thread->enabled = NETDATA_MAIN_THREAD_EXITING;

netdata_log_info("cleaning up...");

pthread_mutex_lock(&deferred_configs_lock);
dyncfg_shutdown = true;
while (deferred_configs != NULL) {
struct deferred_cfg_send *dcs = deferred_configs;
deferred_configs = dcs->next;
deferred_config_free(dcs);
}
pthread_mutex_unlock(&deferred_configs_lock);

static_thread->enabled = NETDATA_MAIN_THREAD_EXITED;
}

void *dyncfg_main(void *ptr)
{
netdata_thread_cleanup_push(dyncfg_cleanup, ptr);

while (!netdata_exit) {
struct deferred_cfg_send *dcs = deferred_config_pop();
struct deferred_cfg_send *dcs = deferred_config_pop(ptr);
const DICTIONARY_ITEM *plugin_item = dictionary_get_and_acquire_item(plugins_dict, dcs->plugin_name);
if (plugin_item == NULL) {
error_report("DYNCFG, plugin %s not found", dcs->plugin_name);
Expand Down Expand Up @@ -905,5 +943,7 @@ void *dyncfg_main(void *in)
deferred_config_free(dcs);
dictionary_acquired_item_release(plugins_dict, plugin_item);
}

netdata_thread_cleanup_pop(1);
return NULL;
}
33 changes: 33 additions & 0 deletions libnetdata/threads/threads.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,39 @@ typedef enum {

typedef pthread_t netdata_thread_t;

struct netdata_static_thread {
// the name of the thread as it should appear in the logs
char *name;

// the section of netdata.conf to check if this is enabled or not
char *config_section;

// the name of the config option to check if it is true or false
char *config_name;

// the current status of the thread
volatile sig_atomic_t enabled;

// internal use, to maintain a pointer to the created thread
netdata_thread_t *thread;

// an initialization function to run before spawning the thread
void (*init_routine) (void);

// the threaded worker
void *(*start_routine) (void *);

// the environment variable to create
char *env_name;

// global variable
bool *global_variable;
};

#define NETDATA_MAIN_THREAD_RUNNING CONFIG_BOOLEAN_YES
#define NETDATA_MAIN_THREAD_EXITING (CONFIG_BOOLEAN_YES + 1)
#define NETDATA_MAIN_THREAD_EXITED CONFIG_BOOLEAN_NO

#define NETDATA_THREAD_TAG_MAX 100
const char *netdata_thread_tag(void);
int netdata_thread_tag_exists(void);
Expand Down