static int check_respawn_thread(thread_t * thread) { pid_t pid; /* Fetch thread args */ pid = THREAD_CHILD_PID(thread); /* Restart respawning thread */ if (thread->type == THREAD_CHILD_TIMEOUT) { thread_add_child(master, check_respawn_thread, NULL, pid, RESPAWN_TIMER); return 0; } /* We catch a SIGCHLD, handle it */ if (!__test_bit(DONT_RESPAWN_BIT, &debug)) { log_message(LOG_ALERT, "Healthcheck child process(%d) died: Respawning", pid); start_check_child(); } else { log_message(LOG_ALERT, "Healthcheck child process(%d) died: Exiting", pid); raise(SIGTERM); } return 0; }
/* VRRP Child respawning thread */ int vrrp_respawn_thread(thread_t * thread) { pid_t pid; /* Fetch thread args */ pid = THREAD_CHILD_PID(thread); /* Restart respawning thread */ if (thread->type == THREAD_CHILD_TIMEOUT) { thread_add_child(master, vrrp_respawn_thread, NULL, pid, RESPAWN_TIMER); return 0; } /* We catch a SIGCHLD, handle it */ if (!(debug & 64)) { log_message(LOG_ALERT, "VRRP child process(%d) died: Respawning", pid); start_vrrp_child(); } else { log_message(LOG_ALERT, "VRRP child process(%d) died: Exiting", pid); raise(SIGTERM); } return 0; }
/* VRRP Child respawning thread */ int vrrp_respawn_thread(thread * thread_obj) { pid_t pid; /* Fetch thread args */ pid = THREAD_CHILD_PID(thread_obj); /* Restart respawning thread */ if (thread_obj->type == THREAD_CHILD_TIMEOUT) { thread_add_child(master, vrrp_respawn_thread, NULL, pid, RESPAWN_TIMER); return 0; } /* We catch a SIGCHLD, handle it */ log_message(LOG_INFO, "VRRP child process(%d) died: Respawning", pid); start_vrrp_child(); return 0; }
/* Register CHECK thread */ int start_check_child(void) { #ifndef _DEBUG_ pid_t pid; int ret; char *syslog_ident; /* Initialize child process */ pid = fork(); if (pid < 0) { log_message(LOG_INFO, "Healthcheck child process: fork error(%s)" , strerror(errno)); return -1; } else if (pid) { checkers_child = pid; log_message(LOG_INFO, "Starting Healthcheck child process, pid=%d" , pid); /* Start respawning thread */ thread_add_child(master, check_respawn_thread, NULL, pid, RESPAWN_TIMER); return 0; } if ((instance_name #if HAVE_DECL_CLONE_NEWNET || network_namespace #endif ) && (check_syslog_ident = make_syslog_ident(PROG_CHECK))) syslog_ident = check_syslog_ident; else syslog_ident = PROG_CHECK; /* Opening local CHECK syslog channel */ openlog(syslog_ident, LOG_PID | ((__test_bit(LOG_CONSOLE_BIT, &debug)) ? LOG_CONS : 0) , (log_facility==LOG_DAEMON) ? LOG_LOCAL2 : log_facility); #ifdef _MEM_CHECK_ mem_log_init(PROG_CHECK, "Healthcheck child process"); #endif free_parent_mallocs_startup(true); /* Child process part, write pidfile */ if (!pidfile_write(checkers_pidfile, getpid())) { log_message(LOG_INFO, "Healthcheck child process: cannot write pidfile"); exit(KEEPALIVED_EXIT_FATAL); } /* Create the new master thread */ signal_handler_destroy(); thread_destroy_master(master); /* This destroys any residual settings from the parent */ master = thread_make_master(); /* change to / dir */ ret = chdir("/"); if (ret < 0) { log_message(LOG_INFO, "Healthcheck child process: error chdir"); } /* Set mask */ umask(0); #endif /* If last process died during a reload, we can get there and we * don't want to loop again, because we're not reloading anymore. */ UNSET_RELOAD; /* Signal handling initialization */ check_signal_init(); /* Start Healthcheck daemon */ start_check(); /* Launch the scheduling I/O multiplexer */ launch_scheduler(); /* Finish healthchecker daemon process */ stop_check(EXIT_SUCCESS); /* unreachable */ exit(EXIT_SUCCESS); }
/* Register VRRP thread */ int start_vrrp_child(void) { #ifndef _DEBUG_ pid_t pid; int ret; /* Initialize child process */ pid = fork(); if (pid < 0) { log_message(LOG_INFO, "VRRP child process: fork error(%s)" , strerror(errno)); return -1; } else if (pid) { vrrp_child = pid; log_message(LOG_INFO, "Starting VRRP child process, pid=%d" , pid); /* Start respawning thread */ thread_add_child(master, vrrp_respawn_thread, NULL, pid, RESPAWN_TIMER); return 0; } signal_handler_destroy(); /* Opening local VRRP syslog channel */ openlog(PROG_VRRP, LOG_PID | ((__test_bit(LOG_CONSOLE_BIT, &debug)) ? LOG_CONS : 0) , (log_facility==LOG_DAEMON) ? LOG_LOCAL1 : log_facility); /* Child process part, write pidfile */ if (!pidfile_write(vrrp_pidfile, getpid())) { /* Fatal error */ log_message(LOG_INFO, "VRRP child process: cannot write pidfile"); exit(0); } /* Create the new master thread */ thread_destroy_master(master); master = thread_make_master(); /* change to / dir */ ret = chdir("/"); if (ret < 0) { log_message(LOG_INFO, "VRRP child process: error chdir"); } /* Set mask */ umask(0); #endif /* If last process died during a reload, we can get there and we * don't want to loop again, because we're not reloading anymore. */ UNSET_RELOAD; /* Signal handling initialization */ vrrp_signal_init(); /* Start VRRP daemon */ start_vrrp(); /* Launch the scheduling I/O multiplexer */ launch_scheduler(); /* Finish VRRP daemon process */ stop_vrrp(); exit(0); }
int misc_check_child_thread(thread * thread_obj) { int wait_status; checker *checker_obj; misc_checker *misc_chk; checker_obj = THREAD_ARG(thread_obj); misc_chk = CHECKER_ARG(checker_obj); if (thread_obj->type == THREAD_CHILD_TIMEOUT) { pid_t pid; pid = THREAD_CHILD_PID(thread_obj); /* The child hasn't responded. Kill it off. */ if (svr_checker_up(checker_obj->id, checker_obj->rs)) { log_message(LOG_INFO, "Misc check to [%s] for [%s] timed out", inet_ntop2(CHECKER_RIP(checker_obj)), misc_chk->path); smtp_alert(checker_obj->rs, NULL, NULL, "DOWN", "=> MISC CHECK script timeout on service <="); update_svr_checker_state(DOWN, checker_obj->id , checker_obj->vs , checker_obj->rs); } kill(pid, SIGTERM); thread_add_child(thread_obj->master, misc_check_child_timeout_thread, checker_obj, pid, 2); return 0; } wait_status = THREAD_CHILD_STATUS(thread_obj); if (WIFEXITED(wait_status)) { int status; status = WEXITSTATUS(wait_status); if (status == 0 || (misc_chk->dynamic == 1 && status >= 2 && status <= 255)) { /* * The actual weight set when using misc_dynamic is two less than * the exit status returned. Effective range is 0..253. * Catch legacy case of status being 0 but misc_dynamic being set. */ if (misc_chk->dynamic == 1 && status != 0) update_svr_wgt(status - 2, checker_obj->vs, checker_obj->rs); /* everything is good */ if (!svr_checker_up(checker_obj->id, checker_obj->rs)) { log_message(LOG_INFO, "Misc check to [%s] for [%s] success.", inet_ntop2(CHECKER_RIP(checker_obj)), misc_chk->path); smtp_alert(checker_obj->rs, NULL, NULL, "UP", "=> MISC CHECK succeed on service <="); update_svr_checker_state(UP, checker_obj->id , checker_obj->vs , checker_obj->rs); } } else { if (svr_checker_up(checker_obj->id, checker_obj->rs)) { log_message(LOG_INFO, "Misc check to [%s] for [%s] failed.", inet_ntop2(CHECKER_RIP(checker_obj)), misc_chk->path); smtp_alert(checker_obj->rs, NULL, NULL, "DOWN", "=> MISC CHECK failed on service <="); update_svr_checker_state(DOWN, checker_obj->id , checker_obj->vs , checker_obj->rs); } } } return 0; }
int misc_check_thread(thread * thread_obj) { checker *checker_obj; misc_checker *misc_chk; int status, ret; pid_t pid; checker_obj = THREAD_ARG(thread_obj); misc_chk = CHECKER_ARG(checker_obj); /* * Register a new checker thread & return * if checker is disabled */ if (!CHECKER_ENABLED(checker_obj)) { /* Register next timer checker */ thread_add_timer(thread_obj->master, misc_check_thread, checker_obj, checker_obj->vs->delay_loop); return 0; } /* Register next timer checker */ thread_add_timer(thread_obj->master, misc_check_thread, checker_obj, checker_obj->vs->delay_loop); /* Daemonization to not degrade our scheduling timer */ pid = fork(); /* In case of fork is error. */ if (pid < 0) { log_message(LOG_INFO, "Failed fork process"); return -1; } /* In case of this is parent process */ if (pid) { long timeout; timeout = (misc_chk->timeout) ? misc_chk->timeout : checker_obj->vs->delay_loop; thread_add_child(thread_obj->master, misc_check_child_thread, checker_obj, pid, timeout); return 0; } /* Child part */ signal_handler_destroy(); closeall(0); open("/dev/null", O_RDWR); ret = dup(0); ret = dup(0); status = system_call(misc_chk->path); if (status < 0 || !WIFEXITED(status)) status = 0; /* Script errors aren't server errors */ else status = WEXITSTATUS(status); exit(status); }