int main(int argc, char **argv) { simple_worker *wp; int i; #ifdef HAVE_SIGACTION struct sigaction sig_action; sig_action.sa_sigaction = NULL; sigfillset(&sig_action.sa_mask); sig_action.sa_flags=SA_NOCLDSTOP; sig_action.sa_handler = child_exited; sigaction(SIGCHLD, &sig_action, NULL); sig_action.sa_flags = SA_NODEFER|SA_RESTART; sig_action.sa_handler = sighandler; sigfillset(&sig_action.sa_mask); sigaction(SIGINT, &sig_action, NULL); sigaction(SIGPIPE, &sig_action, NULL); #else /* HAVE_SIGACTION */ signal(SIGINT, sighandler); signal(SIGPIPE, sighandler); signal(SIGCHLD, child_exited); #endif /* HAVE_SIGACTION */ iobs = iobroker_create(); if (!iobs) die("Failed to create io broker set"); for (i = 0; i < NWPS; i++) { wp = spawn_worker(print_some_crap, "lalala"); if (!wp) { die("Failed to spawn worker(s)\n"); } wps[i] = wp; printf("Registering worker sd %d with io broker\n", wp->sd); iobroker_register(iobs, wp->sd, wp, print_input); } iobroker_register(iobs, fileno(stdin), NULL, send_command); /* get to work */ while (!sigreceived && iobroker_get_num_fds(iobs)) { iobroker_poll(iobs, -1); } for (i = 0; i < NWPS; i++) { kill(wps[i]->pid, SIGKILL); } return 0; }
/* reap 'jobs' jobs or 'secs' seconds, whichever comes first */ void wproc_reap(int jobs, int msecs) { time_t start, now; start = time(NULL); /* one input equals one job (or close enough to it anyway) */ do { int inputs; now = time(NULL); inputs = iobroker_poll(nagios_iobs, (now - start) * 1000); jobs -= inputs; } while (jobs > 0 && start + (msecs * 1000) <= now); }
int main(int argc, char **argv) { int listen_fd, flags, sockopt = 1; struct sockaddr_in sain; int error; const char *err_msg; t_set_colors(0); t_start("iobroker ipc test"); error = iobroker_get_max_fds(NULL); ok_int(error, IOBROKER_ENOSET, "test errors when passing null"); err_msg = iobroker_strerror(error); test(err_msg && !strcmp(err_msg, iobroker_errors[(~error) + 1].string), "iobroker_strerror() returns the right string"); iobs = iobroker_create(); error = iobroker_get_max_fds(iobs); test(iobs && error >= 0, "max fd's for real iobroker set must be > 0"); listen_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); flags = fcntl(listen_fd, F_GETFD); flags |= FD_CLOEXEC; fcntl(listen_fd, F_SETFD, flags); (void)setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, &sockopt, sizeof(sockopt)); memset(&sain, 0, sizeof(sain)); sain.sin_port = ntohs(9123); sain.sin_family = AF_INET; bind(listen_fd, (struct sockaddr *)&sain, sizeof(sain)); listen(listen_fd, 128); iobroker_register(iobs, listen_fd, iobs, listen_handler); if (argc == 1) conn_spam(&sain); for (;;) { iobroker_poll(iobs, -1); if (iobroker_get_num_fds(iobs) <= 1) { break; } } iobroker_close(iobs, listen_fd); iobroker_destroy(iobs, 0); t_end(); return 0; }
/* Try to reap 'jobs' jobs for 'msecs' milliseconds. Return early on error. */ void wproc_reap(int jobs, int msecs) { struct timeval start; gettimeofday(&start, NULL); while (jobs > 0 && msecs > 0) { int inputs = iobroker_poll(nagios_iobs, msecs); if (inputs < 0) return; jobs -= inputs; /* One input is roughly equivalent to one job. */ struct timeval now; gettimeofday(&now, NULL); msecs -= tv_delta_msec(&start, &now); start = now; } }
static int conn_spam(struct sockaddr_in *sain) { int i; signal(SIGALRM, (void (*)(int))sighandler); signal(SIGINT, (void (*)(int))sighandler); signal(SIGPIPE, SIG_IGN); alarm(20); for (i = 0; i < NUM_PROCS; i++) { int fd, sockopt = 1; fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); (void)setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &sockopt, sizeof(sockopt)); proc_counter[i] = 0; iobroker_register(iobs, fd, (void *)&proc_counter[i], connected_handler); if (connect(fd, (struct sockaddr *)sain, sizeof(*sain))) { perror("connect"); } iobroker_poll(iobs, -1); } return 0; }
/* this is the main event handler loop */ int event_execution_loop(void) { timed_event *temp_event, *last_event = NULL; time_t last_time = 0L; time_t current_time = 0L; time_t last_status_update = 0L; int poll_time_ms; log_debug_info(DEBUGL_FUNCTIONS, 0, "event_execution_loop() start\n"); time(&last_time); while (1) { struct timeval now; const struct timeval *event_runtime; int inputs; /* super-priority (hardcoded) events come first */ /* see if we should exit or restart (a signal was encountered) */ if (sigshutdown == TRUE || sigrestart == TRUE) break; /* get the current time */ time(¤t_time); if (sigrotate == TRUE) { rotate_log_file(current_time); update_program_status(FALSE); } /* hey, wait a second... we traveled back in time! */ if (current_time < last_time) compensate_for_system_time_change((unsigned long)last_time, (unsigned long)current_time); /* else if the time advanced over the specified threshold, try and compensate... */ else if ((current_time - last_time) >= time_change_threshold) compensate_for_system_time_change((unsigned long)last_time, (unsigned long)current_time); /* get next scheduled event */ current_event = temp_event = (timed_event *)squeue_peek(nagios_squeue); /* if we don't have any events to handle, exit */ if (!temp_event) { log_debug_info(DEBUGL_EVENTS, 0, "There aren't any events that need to be handled! Exiting...\n"); break; } /* keep track of the last time */ last_time = current_time; /* update status information occassionally - NagVis watches the NDOUtils DB to see if Nagios is alive */ if ((unsigned long)(current_time - last_status_update) > 5) { last_status_update = current_time; update_program_status(FALSE); } event_runtime = squeue_event_runtime(temp_event->sq_event); if (temp_event != last_event) { log_debug_info(DEBUGL_EVENTS, 1, "** Event Check Loop\n"); log_debug_info(DEBUGL_EVENTS, 1, "Next Event Time: %s", ctime(&temp_event->run_time)); log_debug_info(DEBUGL_EVENTS, 1, "Current/Max Service Checks: %d/%d (%.3lf%% saturation)\n", currently_running_service_checks, max_parallel_service_checks, ((float)currently_running_service_checks / (float)max_parallel_service_checks) * 100); } last_event = temp_event; gettimeofday(&now, NULL); poll_time_ms = tv_delta_msec(&now, event_runtime); if (poll_time_ms < 0) poll_time_ms = 0; else if (poll_time_ms >= 1500) poll_time_ms = 1500; log_debug_info(DEBUGL_SCHEDULING, 2, "## Polling %dms; sockets=%d; events=%u; iobs=%p\n", poll_time_ms, iobroker_get_num_fds(nagios_iobs), squeue_size(nagios_squeue), nagios_iobs); inputs = iobroker_poll(nagios_iobs, poll_time_ms); if (inputs < 0 && errno != EINTR) { logit(NSLOG_RUNTIME_ERROR, TRUE, "Error: Polling for input on %p failed: %s", nagios_iobs, iobroker_strerror(inputs)); break; } log_debug_info(DEBUGL_IPC, 2, "## %d descriptors had input\n", inputs); /* * if the event we peaked was removed from the queue from * one of the I/O operations, we must take care not to * try to run at, as we're (almost) sure to access free'd * or invalid memory if we do. */ if (!current_event) { log_debug_info(DEBUGL_EVENTS, 0, "Event was cancelled by iobroker input\n"); continue; } gettimeofday(&now, NULL); if (tv_delta_msec(&now, event_runtime) >= 0) continue; /* move on if we shouldn't run this event */ if (should_run_event(temp_event) == FALSE) continue; /* handle the event */ handle_timed_event(temp_event); /* * we must remove the entry we've peeked, or * we'll keep getting the same one over and over. * This also maintains sync with broker modules. */ remove_event(nagios_squeue, temp_event); /* reschedule the event if necessary */ if (temp_event->recurring == TRUE) reschedule_event(nagios_squeue, temp_event); /* else free memory associated with the event */ else my_free(temp_event); } log_debug_info(DEBUGL_FUNCTIONS, 0, "event_execution_loop() end\n"); return OK; }
static void enter_worker(int sd) { /* created with socketpair(), usually */ master_sd = sd; parent_pid = getppid(); (void)chdir("/tmp"); (void)chdir("nagios-workers"); if (setpgid(0, 0)) { /* XXX: handle error somehow, or maybe just ignore it */ } /* we need to catch child signals the default way */ signal(SIGCHLD, SIG_DFL); fcntl(fileno(stdout), F_SETFD, FD_CLOEXEC); fcntl(fileno(stderr), F_SETFD, FD_CLOEXEC); fcntl(master_sd, F_SETFD, FD_CLOEXEC); iobs = iobroker_create(); if (!iobs) { /* XXX: handle this a bit better */ worker_die("Worker failed to create io broker socket set"); } /* * Create a modest scheduling queue that will be * more than enough for our needs */ sq = squeue_create(1024); set_socket_options(master_sd, 256 * 1024); iobroker_register(iobs, master_sd, NULL, receive_command); while (iobroker_get_num_fds(iobs) > 0) { int poll_time = -1; /* check for timed out jobs */ for (;;) { child_process *cp; struct timeval now, tmo; /* stop when scheduling queue is empty */ cp = (child_process *)squeue_peek(sq); if (!cp) break; tmo.tv_usec = cp->start.tv_usec; tmo.tv_sec = cp->start.tv_sec + cp->timeout; gettimeofday(&now, NULL); poll_time = tv_delta_msec(&now, &tmo); /* * A little extra takes care of rounding errors and * ensures we never kill a job before it times out. * 5 milliseconds is enough to take care of that. */ poll_time += 5; if (poll_time > 0) break; /* this job timed out, so kill it */ wlog("job with pid %d timed out. Killing it", cp->pid); kill_job(cp, ETIME); } iobroker_poll(iobs, poll_time); /* * if our parent goes away we can't really do anything * sensible at all, so let's just break out and exit */ if (kill(parent_pid, 0) < 0 && errno == ESRCH) { break; } } /* we exit when the master shuts us down */ exit(EXIT_SUCCESS); }
int main(int argc, char **argv) { int result; int error = FALSE; int display_license = FALSE; int display_help = FALSE; int c = 0; struct tm *tm, tm_s; time_t now; char datestring[256]; nagios_macros *mac; const char *worker_socket = NULL; int i; #ifdef HAVE_GETOPT_H int option_index = 0; static struct option long_options[] = { {"help", no_argument, 0, 'h'}, {"version", no_argument, 0, 'V'}, {"license", no_argument, 0, 'V'}, {"verify-config", no_argument, 0, 'v'}, {"daemon", no_argument, 0, 'd'}, {"test-scheduling", no_argument, 0, 's'}, {"precache-objects", no_argument, 0, 'p'}, {"use-precached-objects", no_argument, 0, 'u'}, {"enable-timing-point", no_argument, 0, 'T'}, {"worker", required_argument, 0, 'W'}, {0, 0, 0, 0} }; #define getopt(argc, argv, o) getopt_long(argc, argv, o, long_options, &option_index) #endif memset(&loadctl, 0, sizeof(loadctl)); mac = get_global_macros(); /* make sure we have the correct number of command line arguments */ if (argc < 2) error = TRUE; /* get all command line arguments */ while (1) { c = getopt(argc, argv, "+hVvdspuxTW"); if (c == -1 || c == EOF) break; switch (c) { case '?': /* usage */ case 'h': display_help = TRUE; break; case 'V': /* version */ display_license = TRUE; break; case 'v': /* verify */ verify_config++; break; case 's': /* scheduling check */ test_scheduling = TRUE; break; case 'd': /* daemon mode */ daemon_mode = TRUE; break; case 'p': /* precache object config */ precache_objects = TRUE; break; case 'u': /* use precached object config */ use_precached_objects = TRUE; break; case 'T': enable_timing_point = TRUE; break; case 'W': worker_socket = optarg; break; case 'x': printf("Warning: -x is deprecated and will be removed\n"); break; default: break; } } /* if we're a worker we can skip everything below */ if (worker_socket) { exit(nagios_core_worker(worker_socket)); } if (daemon_mode == FALSE) { printf("\nNaemon Core %s\n", PROGRAM_VERSION); printf("Copyright (c) 2013-present Naemon Core Development Team and Community Contributors\n"); printf("Copyright (c) 2009-2013 Nagios Core Development Team and Community Contributors\n"); printf("Copyright (c) 1999-2009 Ethan Galstad\n"); printf("Last Modified: %s\n", PROGRAM_MODIFICATION_DATE); printf("License: GPL\n\n"); printf("Website: http://www.naemon.org\n"); } /* just display the license */ if (display_license == TRUE) { printf("This program is free software; you can redistribute it and/or modify\n"); printf("it under the terms of the GNU General Public License version 2 as\n"); printf("published by the Free Software Foundation.\n\n"); printf("This program is distributed in the hope that it will be useful,\n"); printf("but WITHOUT ANY WARRANTY; without even the implied warranty of\n"); printf("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"); printf("GNU General Public License for more details.\n\n"); printf("You should have received a copy of the GNU General Public License\n"); printf("along with this program; if not, write to the Free Software\n"); printf("Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\n\n"); exit(OK); } /* make sure we got the main config file on the command line... */ if (optind >= argc) error = TRUE; /* if there are no command line options (or if we encountered an error), print usage */ if (error == TRUE || display_help == TRUE) { printf("Usage: %s [options] <main_config_file>\n", argv[0]); printf("\n"); printf("Options:\n"); printf("\n"); printf(" -v, --verify-config Verify all configuration data (-v -v for more info)\n"); printf(" -s, --test-scheduling Shows projected/recommended check scheduling and other\n"); printf(" diagnostic info based on the current configuration files.\n"); printf(" -T, --enable-timing-point Enable timed commentary on initialization\n"); printf(" -x, --dont-verify-paths Deprecated (Don't check for circular object paths)\n"); printf(" -p, --precache-objects Precache object configuration\n"); printf(" -u, --use-precached-objects Use precached object config file\n"); printf(" -d, --daemon Starts Naemon in daemon mode, instead of as a foreground process\n"); printf(" -W, --worker /path/to/socket Act as a worker for an already running daemon\n"); printf("\n"); printf("Visit the Naemon website at http://www.naemon.org/ for bug fixes, new\n"); printf("releases, online documentation, FAQs and more...\n"); printf("\n"); exit(ERROR); } /* * config file is last argument specified. * Make sure it uses an absolute path */ config_file = nspath_absolute(argv[optind], NULL); if (config_file == NULL) { printf("Error allocating memory.\n"); exit(ERROR); } config_file_dir = nspath_absolute_dirname(config_file, NULL); /* * Set the signal handler for the SIGXFSZ signal here because * we may encounter this signal before the other signal handlers * are set. */ signal(SIGXFSZ, handle_sigxfsz); /* * let's go to town. We'll be noisy if we're verifying config * or running scheduling tests. */ if (verify_config || test_scheduling || precache_objects) { reset_variables(); /* * if we don't beef up our resource limits as much as * we can, it's quite possible we'll run headlong into * EAGAIN due to too many processes when we try to * drop privileges later. */ set_loadctl_defaults(); if (verify_config) printf("Reading configuration data...\n"); /* read our config file */ result = read_main_config_file(config_file); if (result != OK) { printf(" Error processing main config file!\n\n"); exit(EXIT_FAILURE); } if (verify_config) printf(" Read main config file okay...\n"); /* drop privileges */ if ((result = drop_privileges(naemon_user, naemon_group)) == ERROR) { printf(" Failed to drop privileges. Aborting."); exit(EXIT_FAILURE); } /* * this must come after dropping privileges, so we make * sure to test access permissions as the right user. */ if (test_configured_paths() == ERROR) { printf(" One or more path problems detected. Aborting.\n"); exit(EXIT_FAILURE); } /* read object config files */ result = read_all_object_data(config_file); if (result != OK) { printf(" Error processing object config files!\n\n"); /* if the config filename looks fishy, warn the user */ if (!strstr(config_file, "naemon.cfg")) { printf("\n***> The name of the main configuration file looks suspicious...\n"); printf("\n"); printf(" Make sure you are specifying the name of the MAIN configuration file on\n"); printf(" the command line and not the name of another configuration file. The\n"); printf(" main configuration file is typically '%s'\n", DEFAULT_CONFIG_FILE); } printf("\n***> One or more problems was encountered while processing the config files...\n"); printf("\n"); printf(" Check your configuration file(s) to ensure that they contain valid\n"); printf(" directives and data defintions. If you are upgrading from a previous\n"); printf(" version of Naemon, you should be aware that some variables/definitions\n"); printf(" may have been removed or modified in this version. Make sure to read\n"); printf(" the HTML documentation regarding the config files, as well as the\n"); printf(" 'Whats New' section to find out what has changed.\n\n"); exit(EXIT_FAILURE); } if (verify_config) { printf(" Read object config files okay...\n\n"); printf("Running pre-flight check on configuration data...\n\n"); } /* run the pre-flight check to make sure things look okay... */ result = pre_flight_check(); if (result != OK) { printf("\n***> One or more problems was encountered while running the pre-flight check...\n"); printf("\n"); printf(" Check your configuration file(s) to ensure that they contain valid\n"); printf(" directives and data defintions. If you are upgrading from a previous\n"); printf(" version of Naemon, you should be aware that some variables/definitions\n"); printf(" may have been removed or modified in this version. Make sure to read\n"); printf(" the HTML documentation regarding the config files, as well as the\n"); printf(" 'Whats New' section to find out what has changed.\n\n"); exit(EXIT_FAILURE); } if (verify_config) { printf("\nThings look okay - No serious problems were detected during the pre-flight check\n"); } /* scheduling tests need a bit more than config verifications */ if (test_scheduling == TRUE) { /* we'll need the event queue here so we can time insertions */ init_event_queue(); timing_point("Done initializing event queue\n"); /* read initial service and host state information */ initialize_retention_data(config_file); read_initial_state_information(); timing_point("Retention data and initial state parsed\n"); /* initialize the event timing loop */ init_timing_loop(); timing_point("Timing loop initialized\n"); /* display scheduling information */ display_scheduling_info(); } if (precache_objects) { result = fcache_objects(object_precache_file); timing_point("Done precaching objects\n"); if (result == OK) { printf("Object precache file created:\n%s\n", object_precache_file); } else { printf("Failed to precache objects to '%s': %s\n", object_precache_file, strerror(errno)); } } /* clean up after ourselves */ cleanup(); /* exit */ timing_point("Exiting\n"); /* make valgrind shut up about still reachable memory */ neb_free_module_list(); free(config_file_dir); free(config_file); exit(result); } /* start to monitor things... */ /* * if we're called with a relative path we must make * it absolute so we can launch our workers. * If not, we needn't bother, as we're using execvp() */ if (strchr(argv[0], '/')) naemon_binary_path = nspath_absolute(argv[0], NULL); else naemon_binary_path = strdup(argv[0]); if (!naemon_binary_path) { logit(NSLOG_RUNTIME_ERROR, TRUE, "Error: Unable to allocate memory for naemon_binary_path\n"); exit(EXIT_FAILURE); } if (!(nagios_iobs = iobroker_create())) { logit(NSLOG_RUNTIME_ERROR, TRUE, "Error: Failed to create IO broker set: %s\n", strerror(errno)); exit(EXIT_FAILURE); } /* keep monitoring things until we get a shutdown command */ do { /* reset internal book-keeping (in case we're restarting) */ wproc_num_workers_spawned = wproc_num_workers_online = 0; caught_signal = sigshutdown = sigrestart = FALSE; sig_id = 0; /* reset program variables */ reset_variables(); timing_point("Variables reset\n"); /* get PID */ nagios_pid = (int)getpid(); /* read in the configuration files (main and resource config files) */ result = read_main_config_file(config_file); if (result != OK) { logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Failed to process config file '%s'. Aborting\n", config_file); exit(EXIT_FAILURE); } timing_point("Main config file read\n"); /* NOTE 11/06/07 EG moved to after we read config files, as user may have overridden timezone offset */ /* get program (re)start time and save as macro */ program_start = time(NULL); my_free(mac->x[MACRO_PROCESSSTARTTIME]); asprintf(&mac->x[MACRO_PROCESSSTARTTIME], "%lu", (unsigned long)program_start); /* drop privileges */ if (drop_privileges(naemon_user, naemon_group) == ERROR) { logit(NSLOG_PROCESS_INFO | NSLOG_RUNTIME_ERROR | NSLOG_CONFIG_ERROR, TRUE, "Failed to drop privileges. Aborting."); cleanup(); exit(ERROR); } if (test_path_access(naemon_binary_path, X_OK)) { logit(NSLOG_RUNTIME_ERROR, TRUE, "Error: failed to access() %s: %s\n", naemon_binary_path, strerror(errno)); logit(NSLOG_RUNTIME_ERROR, TRUE, "Error: Spawning workers will be impossible. Aborting.\n"); exit(EXIT_FAILURE); } if (test_configured_paths() == ERROR) { /* error has already been logged */ exit(EXIT_FAILURE); } /* enter daemon mode (unless we're restarting...) */ if (daemon_mode == TRUE && sigrestart == FALSE) { result = daemon_init(); /* we had an error daemonizing, so bail... */ if (result == ERROR) { logit(NSLOG_PROCESS_INFO | NSLOG_RUNTIME_ERROR, TRUE, "Bailing out due to failure to daemonize. (PID=%d)", (int)getpid()); cleanup(); exit(EXIT_FAILURE); } /* get new PID */ nagios_pid = (int)getpid(); } /* this must be logged after we read config data, as user may have changed location of main log file */ logit(NSLOG_PROCESS_INFO, TRUE, "Naemon %s starting... (PID=%d)\n", PROGRAM_VERSION, (int)getpid()); /* log the local time - may be different than clock time due to timezone offset */ now = time(NULL); tm = localtime_r(&now, &tm_s); strftime(datestring, sizeof(datestring), "%a %b %d %H:%M:%S %Z %Y", tm); logit(NSLOG_PROCESS_INFO, TRUE, "Local time is %s", datestring); /* write log version/info */ write_log_file_info(NULL); /* open debug log now that we're the right user */ open_debug_log(); #ifdef USE_EVENT_BROKER /* initialize modules */ neb_init_modules(); neb_init_callback_list(); #endif timing_point("NEB module API initialized\n"); /* handle signals (interrupts) before we do any socket I/O */ setup_sighandler(); /* * Initialize query handler and event subscription service. * This must be done before modules are initialized, so * the modules can use our in-core stuff properly */ if (qh_init(qh_socket_path ? qh_socket_path : DEFAULT_QUERY_SOCKET) != OK) { logit(NSLOG_RUNTIME_ERROR, TRUE, "Error: Failed to initialize query handler. Aborting\n"); exit(EXIT_FAILURE); } timing_point("Query handler initialized\n"); nerd_init(); timing_point("NERD initialized\n"); /* initialize check workers */ if (init_workers(num_check_workers) < 0) { logit(NSLOG_RUNTIME_ERROR, TRUE, "Failed to spawn workers. Aborting\n"); exit(EXIT_FAILURE); } timing_point("%u workers spawned\n", wproc_num_workers_spawned); i = 0; while (i < 50 && wproc_num_workers_online < wproc_num_workers_spawned) { iobroker_poll(nagios_iobs, 50); i++; } timing_point("%u workers connected\n", wproc_num_workers_online); /* now that workers have arrived we can set the defaults */ set_loadctl_defaults(); /* read in all object config data */ if (result == OK) result = read_all_object_data(config_file); /* * the queue has to be initialized befor loading the neb modules * to give them the chance to register user events. * (initializing event queue requires number of objects, so do * this after parsing the objects) */ init_event_queue(); timing_point("Event queue initialized\n"); #ifdef USE_EVENT_BROKER /* load modules */ if (neb_load_all_modules() != OK) { logit(NSLOG_CONFIG_ERROR, ERROR, "Error: Module loading failed. Aborting.\n"); /* if we're dumping core, we must remove all dl-files */ if (daemon_dumps_core) neb_unload_all_modules(NEBMODULE_FORCE_UNLOAD, NEBMODULE_NEB_SHUTDOWN); exit(EXIT_FAILURE); } timing_point("Modules loaded\n"); /* send program data to broker */ broker_program_state(NEBTYPE_PROCESS_PRELAUNCH, NEBFLAG_NONE, NEBATTR_NONE, NULL); timing_point("First callback made\n"); #endif /* there was a problem reading the config files */ if (result != OK) logit(NSLOG_PROCESS_INFO | NSLOG_RUNTIME_ERROR | NSLOG_CONFIG_ERROR, TRUE, "Bailing out due to one or more errors encountered in the configuration files. Run Naemon from the command line with the -v option to verify your config before restarting. (PID=%d)", (int)getpid()); else { /* run the pre-flight check to make sure everything looks okay*/ if ((result = pre_flight_check()) != OK) logit(NSLOG_PROCESS_INFO | NSLOG_RUNTIME_ERROR | NSLOG_VERIFICATION_ERROR, TRUE, "Bailing out due to errors encountered while running the pre-flight check. Run Naemon from the command line with the -v option to verify your config before restarting. (PID=%d)\n", (int)getpid()); } /* an error occurred that prevented us from (re)starting */ if (result != OK) { /* if we were restarting, we need to cleanup from the previous run */ if (sigrestart == TRUE) { /* clean up the status data */ cleanup_status_data(TRUE); } #ifdef USE_EVENT_BROKER /* send program data to broker */ broker_program_state(NEBTYPE_PROCESS_SHUTDOWN, NEBFLAG_PROCESS_INITIATED, NEBATTR_SHUTDOWN_ABNORMAL, NULL); #endif cleanup(); exit(ERROR); } timing_point("Object configuration parsed and understood\n"); /* write the objects.cache file */ fcache_objects(object_cache_file); timing_point("Objects cached\n"); #ifdef USE_EVENT_BROKER /* send program data to broker */ broker_program_state(NEBTYPE_PROCESS_START, NEBFLAG_NONE, NEBATTR_NONE, NULL); #endif /* initialize status data unless we're starting */ if (sigrestart == FALSE) { initialize_status_data(config_file); timing_point("Status data initialized\n"); } /* initialize scheduled downtime data */ initialize_downtime_data(); timing_point("Downtime data initialized\n"); /* read initial service and host state information */ initialize_retention_data(config_file); timing_point("Retention data initialized\n"); read_initial_state_information(); timing_point("Initial state information read\n"); /* initialize comment data */ initialize_comment_data(); timing_point("Comment data initialized\n"); /* initialize performance data */ initialize_performance_data(config_file); timing_point("Performance data initialized\n"); /* initialize the event timing loop */ init_timing_loop(); timing_point("Event timing loop initialized\n"); /* initialize check statistics */ init_check_stats(); timing_point("check stats initialized\n"); /* update all status data (with retained information) */ update_all_status_data(); timing_point("Status data updated\n"); /* log initial host and service state */ log_host_states(INITIAL_STATES, NULL); log_service_states(INITIAL_STATES, NULL); timing_point("Initial states logged\n"); /* reset the restart flag */ sigrestart = FALSE; /* fire up command file worker */ launch_command_file_worker(); timing_point("Command file worker launched\n"); #ifdef USE_EVENT_BROKER /* send program data to broker */ broker_program_state(NEBTYPE_PROCESS_EVENTLOOPSTART, NEBFLAG_NONE, NEBATTR_NONE, NULL); #endif /* get event start time and save as macro */ event_start = time(NULL); my_free(mac->x[MACRO_EVENTSTARTTIME]); asprintf(&mac->x[MACRO_EVENTSTARTTIME], "%lu", (unsigned long)event_start); timing_point("Entering event execution loop\n"); /***** start monitoring all services *****/ /* (doesn't return until a restart or shutdown signal is encountered) */ event_execution_loop(); /* * immediately deinitialize the query handler so it * can remove modules that have stashed data with it */ qh_deinit(qh_socket_path ? qh_socket_path : DEFAULT_QUERY_SOCKET); /* 03/01/2007 EG Moved from sighandler() to prevent FUTEX locking problems under NPTL */ /* 03/21/2007 EG SIGSEGV signals are still logged in sighandler() so we don't loose them */ /* did we catch a signal? */ if (caught_signal == TRUE) { if (sig_id == SIGHUP) logit(NSLOG_PROCESS_INFO, TRUE, "Caught SIGHUP, restarting...\n"); } #ifdef USE_EVENT_BROKER /* send program data to broker */ broker_program_state(NEBTYPE_PROCESS_EVENTLOOPEND, NEBFLAG_NONE, NEBATTR_NONE, NULL); if (sigshutdown == TRUE) broker_program_state(NEBTYPE_PROCESS_SHUTDOWN, NEBFLAG_USER_INITIATED, NEBATTR_SHUTDOWN_NORMAL, NULL); else if (sigrestart == TRUE) broker_program_state(NEBTYPE_PROCESS_RESTART, NEBFLAG_USER_INITIATED, NEBATTR_RESTART_NORMAL, NULL); #endif disconnect_command_file_worker(); /* save service and host state information */ save_state_information(FALSE); cleanup_retention_data(); /* clean up performance data */ cleanup_performance_data(); /* clean up the scheduled downtime data */ cleanup_downtime_data(); /* clean up the status data unless we're restarting */ if (sigrestart == FALSE) { cleanup_status_data(TRUE); } free_worker_memory(WPROC_FORCE); /* shutdown stuff... */ if (sigshutdown == TRUE) { iobroker_destroy(nagios_iobs, IOBROKER_CLOSE_SOCKETS); nagios_iobs = NULL; /* log a shutdown message */ logit(NSLOG_PROCESS_INFO, TRUE, "Successfully shutdown... (PID=%d)\n", (int)getpid()); } /* clean up after ourselves */ cleanup(); /* close debug log */ close_debug_log(); } while (sigrestart == TRUE && sigshutdown == FALSE); if (daemon_mode == TRUE) unlink(lock_file); /* free misc memory */ my_free(lock_file); my_free(config_file); my_free(config_file_dir); my_free(naemon_binary_path); return OK; }