}
void *backends_main(void *ptr) {
- (void)ptr;
+ struct netdata_static_thread *static_thread = (struct netdata_static_thread *)ptr;
BUFFER *b = buffer_create(1), *response = buffer_create(1);
int (*backend_request_formatter)(BUFFER *b, const char *prefix, RRDHOST *host, const char *hostname, RRDSET *st, RRDDIM *rd, time_t after, time_t before, uint32_t options) = NULL;
info("BACKEND thread exiting");
+ static_thread->enabled = 0;
+ static_thread->thread = NULL;
pthread_exit(NULL);
return NULL;
}
}
void *health_main(void *ptr) {
- (void)ptr;
+ struct netdata_static_thread *static_thread = (struct netdata_static_thread *)ptr;
info("HEALTH thread created with task id %d", gettid());
buffer_free(wb);
info("HEALTH thread exiting");
+
+ static_thread->enabled = 0;
+ static_thread->thread = NULL;
pthread_exit(NULL);
return NULL;
}
debug(D_EXIT, "Called: netdata_cleanup_and_exit()");
#ifdef NETDATA_INTERNAL_CHECKS
+ kill_childs();
rrdset_free_all();
#else
rrdset_save_all();
exit(ret);
}
-struct netdata_static_thread {
- char *name;
-
- char *config_section;
- char *config_name;
-
- int enabled;
-
- pthread_t *thread;
-
- void (*init_routine) (void);
- void *(*start_routine) (void *);
-} static_threads[] = {
+struct netdata_static_thread static_threads[] = {
#ifdef INTERNAL_PLUGIN_NFACCT
// nfacct requires root access
// so, we build it as an external plugin with setuid to root
void kill_childs()
{
+ error_log_limit_unlimited();
+
siginfo_t info;
struct web_client *w;
for(w = web_clients; w ; w = w->next) {
- debug(D_EXIT, "Stopping web client %s", w->client_ip);
+ info("Stopping web client %s", w->client_ip);
pthread_cancel(w->thread);
- pthread_join(w->thread, NULL);
+ // it is detached
+ // pthread_join(w->thread, NULL);
}
int i;
for (i = 0; static_threads[i].name != NULL ; i++) {
- if(static_threads[i].thread) {
- debug(D_EXIT, "Stopping %s thread", static_threads[i].name);
+ if(static_threads[i].enabled && static_threads[i].thread) {
+ info("Stopping %s thread", static_threads[i].name);
pthread_cancel(*static_threads[i].thread);
- pthread_join(*static_threads[i].thread, NULL);
+ // it is detached
+ // pthread_join(*static_threads[i].thread, NULL);
+
static_threads[i].thread = NULL;
}
}
if(tc_child_pid) {
- debug(D_EXIT, "Killing tc-qos-helper procees");
+ info("Killing tc-qos-helper process %d", tc_child_pid);
if(killpid(tc_child_pid, SIGTERM) != -1)
waitid(P_PID, (id_t) tc_child_pid, &info, WEXITED);
}
struct plugind *cd;
for(cd = pluginsd_root ; cd ; cd = cd->next) {
- debug(D_EXIT, "Stopping %s plugin thread", cd->id);
- pthread_cancel(cd->thread);
- pthread_join(cd->thread, NULL);
-
- if(cd->pid && !cd->obsolete) {
- debug(D_EXIT, "killing %s plugin process", cd->id);
- if(killpid(cd->pid, SIGTERM) != -1)
- waitid(P_PID, (id_t) cd->pid, &info, WEXITED);
+ if(!cd->obsolete) {
+ if(cd->thread) {
+ info("Stopping %s plugin thread", cd->id);
+ pthread_cancel(cd->thread);
+ // they are detached
+ // pthread_join(cd->thread, NULL);
+ }
+
+ if(cd->pid) {
+ info("killing %s plugin child process pid %d", cd->id, cd->pid);
+ if(killpid(cd->pid, SIGTERM) != -1)
+ waitid(P_PID, (id_t) cd->pid, &info, WEXITED);
+
+ cd->pid = 0;
+ }
+
+ cd->obsolete = 1;
}
}
// if, for any reason there is any child exited
// catch it here
+ info("Cleaning up an other children");
waitid(P_PID, 0, &info, WEXITED|WNOHANG);
- debug(D_EXIT, "All threads/childs stopped.");
+ info("All threads/childs stopped.");
}
struct option_def options[] = {
debug(D_SYSTEM, "Starting thread %s.", st->name);
- if(pthread_create(st->thread, &attr, st->start_routine, NULL))
+ if(pthread_create(st->thread, &attr, st->start_routine, st))
error("failed to create new thread for %s.", st->name);
else if(pthread_detach(*st->thread))
*/
extern struct option_def options[];
+
+struct netdata_static_thread {
+ char *name;
+
+ char *config_section;
+ char *config_name;
+
+ volatile int enabled;
+
+ pthread_t *thread;
+
+ void (*init_routine) (void);
+ void *(*start_routine) (void *);
+};
+
extern void kill_childs(void);
extern int killpid(pid_t pid, int signal);
extern void netdata_cleanup_and_exit(int ret) NORETURN;
#include "common.h"
-void *checks_main(void *ptr)
-{
- if(ptr) { ; }
+void *checks_main(void *ptr) {
+ struct netdata_static_thread *static_thread = (struct netdata_static_thread *)ptr;
info("CHECKS thread created with task id %d", gettid());
rrdset_done(check3);
}
+ info("CHECKS thread exiting");
+
+ static_thread->enabled = 0;
+ static_thread->thread = NULL;
pthread_exit(NULL);
return NULL;
}
#include "common.h"
-void *freebsd_main(void *ptr)
-{
- (void)ptr;
+void *freebsd_main(void *ptr) {
+ struct netdata_static_thread *static_thread = (struct netdata_static_thread *)ptr;
info("FREEBSD Plugin thread created with task id %d", gettid());
info("FREEBSD thread exiting");
+ static_thread->enabled = 0;
+ static_thread->thread = NULL;
pthread_exit(NULL);
return NULL;
}
#define CPU_IDLEJITTER_SLEEP_TIME_MS 20
-void *cpuidlejitter_main(void *ptr)
-{
- if(ptr) { ; }
+void *cpuidlejitter_main(void *ptr) {
+ struct netdata_static_thread *static_thread = (struct netdata_static_thread *)ptr;
- info("CPU Idle Jitter thread created with task id %d", gettid());
+ info("IDLEJITTER thread created with task id %d", gettid());
if(pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL) != 0)
error("Cannot set pthread cancel type to DEFERRED.");
rrdset_done(st);
}
+ info("IDLEJITTER thread exiting");
+
+ static_thread->enabled = 0;
+ static_thread->thread = NULL;
pthread_exit(NULL);
return NULL;
}
#include "common.h"
-void *macos_main(void *ptr)
-{
- (void)ptr;
+void *macos_main(void *ptr) {
+ struct netdata_static_thread *static_thread = (struct netdata_static_thread *)ptr;
info("MACOS Plugin thread created with task id %d", gettid());
info("MACOS thread exiting");
+ static_thread->enabled = 0;
+ static_thread->thread = NULL;
pthread_exit(NULL);
return NULL;
}
}
void *nfacct_main(void *ptr) {
- if(ptr) { ; }
+ struct netdata_static_thread *static_thread = (struct netdata_static_thread *)ptr;
info("NFACCT thread created with task id %d", gettid());
nl = mnl_socket_open(NETLINK_NETFILTER);
if(!nl) {
error("nfacct.plugin: mnl_socket_open() failed");
- pthread_exit(NULL);
- return NULL;
+ goto cleanup;
}
if(mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) {
- mnl_socket_close(nl);
error("nfacct.plugin: mnl_socket_bind() failed");
- pthread_exit(NULL);
- return NULL;
+ goto cleanup;
}
portid = mnl_socket_get_portid(nl);
nlh = nfacct_nlmsg_build_hdr(buf, NFNL_MSG_ACCT_GET, NLM_F_DUMP, seq);
if(!nlh) {
- mnl_socket_close(nl);
error("nfacct.plugin: nfacct_nlmsg_build_hdr() failed");
- pthread_exit(NULL);
- return NULL;
+ goto cleanup;
}
if(mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) {
error("nfacct.plugin: mnl_socket_send");
- pthread_exit(NULL);
- return NULL;
+ goto cleanup;
}
if(nfacct_list) nfacct_list->len = 0;
if (ret == -1) {
error("nfacct.plugin: error communicating with kernel.");
- pthread_exit(NULL);
- return NULL;
+ goto cleanup;
}
// --------------------------------------------------------------------
memmove(&last, &now, sizeof(struct timeval));
}
- mnl_socket_close(nl);
+cleanup:
+ info("NFACCT thread exiting");
+
+ if(nl) mnl_socket_close(nl);
+
+ static_thread->enabled = 0;
+ static_thread->thread = NULL;
pthread_exit(NULL);
return NULL;
}
{ .name = NULL, .dim = NULL, .func = NULL }
};
-void *proc_main(void *ptr)
-{
- (void)ptr;
+void *proc_main(void *ptr) {
+ struct netdata_static_thread *static_thread = (struct netdata_static_thread *)ptr;
info("PROC Plugin thread created with task id %d", gettid());
info("PROC thread exiting");
+ static_thread->enabled = 0;
+ static_thread->thread = NULL;
pthread_exit(NULL);
return NULL;
}
pid_t tc_child_pid = 0;
void *tc_main(void *ptr) {
- (void)ptr;
+ struct netdata_static_thread *static_thread = (struct netdata_static_thread *)ptr;
info("TC thread created with task id %d", gettid());
fp = mypopen(buffer, &tc_child_pid);
if(unlikely(!fp)) {
error("TC: Cannot popen(\"%s\", \"r\").", buffer);
- pthread_exit(NULL);
- return NULL;
+ goto cleanup;
}
while(fgets(buffer, TC_LINE_MAX, fp) != NULL) {
if(unlikely(netdata_exit)) {
tc_device_free_all();
- pthread_exit(NULL);
- return NULL;
+ goto cleanup;
}
if(code == 1 || code == 127) {
error("TC: tc-qos-helper.sh exited with code %d. Disabling it.", code);
tc_device_free_all();
- pthread_exit(NULL);
- return NULL;
+ goto cleanup;
}
sleep((unsigned int) rrd_update_every);
}
+cleanup:
+ info("TC thread exiting");
+
+ static_thread->enabled = 0;
+ static_thread->thread = NULL;
pthread_exit(NULL);
return NULL;
}
info("PLUGINSD: '%s' thread exiting", cd->fullfilename);
cd->obsolete = 1;
+ cd->thread = 0;
pthread_exit(NULL);
return NULL;
}
void *pluginsd_main(void *ptr) {
- (void)ptr;
+ struct netdata_static_thread *static_thread = (struct netdata_static_thread *)ptr;
info("PLUGINS.D thread created with task id %d", gettid());
dir = opendir(dir_name);
if(unlikely(!dir)) {
error("Cannot open directory '%s'.", dir_name);
- pthread_exit(NULL);
- return NULL;
+ goto cleanup;
}
while(likely((file = readdir(dir)))) {
}
cd->obsolete = 0;
- if(unlikely(!cd->enabled)) continue;
+ if(unlikely(!cd->enabled)) {
+ cd->obsolete = 1;
+ continue;
+ }
// spawn a new thread for it
if(unlikely(pthread_create(&cd->thread, NULL, pluginsd_worker_thread, cd) != 0)) {
}
else if(unlikely(pthread_detach(cd->thread) != 0))
error("PLUGINSD: Cannot request detach of newly created thread for plugin '%s'.", cd->filename);
+
}
closedir(dir);
sleep((unsigned int) scan_frequency);
}
+cleanup:
info("PLUGINS.D thread exiting");
+ static_thread->enabled = 0;
+ static_thread->thread = NULL;
pthread_exit(NULL);
return NULL;
}
// without collecting values
int update_every; // the plugin default data collection frequency
- int obsolete; // do not touch this structure after setting this to 1
+ volatile int obsolete; // do not touch this structure after setting this to 1
int enabled; // if this is enabled or not
time_t started_t;
RRDDIM *rrddim_add(RRDSET *st, const char *id, const char *name, long multiplier, long divisor, int algorithm)
{
+ RRDDIM *rd = rrddim_find(st, id);
+ if(rd) {
+ error("Cannot create rrd dimension '%s/%s', it already exists.", st->id, name);
+ return rd;
+ }
+
char filename[FILENAME_MAX + 1];
char fullfilename[FILENAME_MAX + 1];
char varname[CONFIG_MAX_NAME + 1];
- RRDDIM *rd = NULL;
unsigned long size = sizeof(RRDDIM) + (st->entries * sizeof(storage_number));
debug(D_RRD_CALLS, "Adding dimension '%s/%s'.", st->id, id);
rrdset_strncpyz_name(filename, id, FILENAME_MAX);
snprintfz(fullfilename, FILENAME_MAX, "%s/%s.db", st->cache_dir, filename);
- if(rrd_memory_mode != RRD_MEMORY_MODE_RAM) rd = (RRDDIM *)mymmap(fullfilename, size, ((rrd_memory_mode == RRD_MEMORY_MODE_MAP)?MAP_SHARED:MAP_PRIVATE), 1);
+
+ if(rrd_memory_mode != RRD_MEMORY_MODE_RAM)
+ rd = (RRDDIM *)mymmap(fullfilename, size, ((rrd_memory_mode == RRD_MEMORY_MODE_MAP)?MAP_SHARED:MAP_PRIVATE), 1);
+
if(rd) {
struct timeval now;
now_realtime_timeval(&now);
RRDSET *st;
RRDDIM *rd;
- rrdhost_rwlock(&localhost);
+ rrdhost_rdlock(&localhost);
for(st = localhost.rrdset_root; st ; st = st->next) {
- pthread_rwlock_wrlock(&st->rwlock);
+ pthread_rwlock_rdlock(&st->rwlock);
if(st->mapped == RRD_MEMORY_MODE_SAVE) {
debug(D_RRD_CALLS, "Saving stats '%s' to '%s'.", st->name, st->cache_filename);
return 0;
}
-void *cgroups_main(void *ptr)
-{
- (void)ptr;
+void *cgroups_main(void *ptr) {
+ struct netdata_static_thread *static_thread = (struct netdata_static_thread *)ptr;
info("CGROUP Plugin thread created with task id %d", gettid());
info("CGROUP thread exiting");
+ static_thread->enabled = 0;
+ static_thread->thread = NULL;
pthread_exit(NULL);
return NULL;
}
#define CLEANUP_EVERY_EVENTS 100
void *socket_listen_main_multi_threaded(void *ptr) {
- (void)ptr;
+ struct netdata_static_thread *static_thread = (struct netdata_static_thread *)ptr;
web_server_mode = WEB_SERVER_MODE_MULTI_THREADED;
info("Multi-threaded WEB SERVER thread created with task id %d", gettid());
debug(D_WEB_CLIENT, "LISTENER: exit!");
close_listen_sockets();
+ static_thread->enabled = 0;
+ static_thread->thread = NULL;
+ pthread_exit(NULL);
return NULL;
}
}
void *socket_listen_main_single_threaded(void *ptr) {
- (void)ptr;
+ struct netdata_static_thread *static_thread = (struct netdata_static_thread *)ptr;
web_server_mode = WEB_SERVER_MODE_SINGLE_THREADED;
debug(D_WEB_CLIENT, "LISTENER: exit!");
close_listen_sockets();
+
+ static_thread->enabled = 0;
+ static_thread->thread = NULL;
+ pthread_exit(NULL);
return NULL;
}