From: <ag...@us...> - 2012-12-19 16:51:45
|
Revision: 2540 http://nagios.svn.sourceforge.net/nagios/?rev=2540&view=rev Author: ageric Date: 2012-12-19 16:51:38 +0000 (Wed, 19 Dec 2012) Log Message: ----------- core: Daemonize before we open any persistent files Once upon a time there was a keepalive daemon that figured it would be a mighty fine idea if it closed stdin, stdout and stderr for the programs it launched. That was kinda stupid, since it caused Nagios to fail to use its IO broker set. The same sort of thing can happen with logfiles and other things that uses filedescriptors, of all kinds, so we avoid opening *any* persistent files before we're done close()'ing stdin, stdout and stderr. This means we no longer print the "Finished daemonizing..." message in the logfile, since it would look pretty stupid there *after* the "Nagios starting" message (which now prints the correct pid the first time around, btw). It also means we never load or initialize modules in any way before we're done daemonizing, since we'd only have to unload them if we fail, and they could be subject to the same "oopsie, I killed your filedescriptor" issue as Nagios core was under such exceptionally weird and hard-to-debug circumstances. Signed-off-by: Andreas Ericsson <ae...@op...> Modified Paths: -------------- nagioscore/trunk/base/nagios.c nagioscore/trunk/base/utils.c Modified: nagioscore/trunk/base/nagios.c =================================================================== --- nagioscore/trunk/base/nagios.c 2012-12-19 16:51:13 UTC (rev 2539) +++ nagioscore/trunk/base/nagios.c 2012-12-19 16:51:38 UTC (rev 2540) @@ -137,7 +137,6 @@ int main(int argc, char **argv, char **env) { int result; int error = FALSE; - char *buffer = NULL; int display_license = FALSE; int display_help = FALSE; int c = 0; @@ -481,22 +480,28 @@ exit(ERROR); } - /* open debug log now that we're the right user */ - open_debug_log(); - if (access(nagios_binary_path, X_OK) < 0) { logit(NSLOG_RUNTIME_ERROR, TRUE, "Error: failed to access() %s: %s\n", nagios_binary_path, strerror(errno)); logit(NSLOG_RUNTIME_ERROR, TRUE, "Error: Spawning workers will be impossible. Aborting.\n"); exit(EXIT_FAILURE); } -#ifdef USE_EVENT_BROKER - /* initialize modules */ - neb_init_modules(); - neb_init_callback_list(); -#endif - timing_point("NEB module API initialized\n"); + /* 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, "Nagios %s starting... (PID=%d)\n", PROGRAM_VERSION, (int)getpid()); @@ -509,6 +514,16 @@ /* 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(); @@ -599,31 +614,6 @@ broker_program_state(NEBTYPE_PROCESS_START, NEBFLAG_NONE, NEBATTR_NONE, NULL); #endif - /* 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()); - -#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); - } - - asprintf(&buffer, "Finished daemonizing... (New PID=%d)\n", (int)getpid()); - write_to_all_logs(buffer, NSLOG_PROCESS_INFO); - my_free(buffer); - - /* get new PID */ - nagios_pid = (int)getpid(); - } - /* initialize status data unless we're starting */ if(sigrestart == FALSE) { initialize_status_data(config_file); Modified: nagioscore/trunk/base/utils.c =================================================================== --- nagioscore/trunk/base/utils.c 2012-12-19 16:51:13 UTC (rev 2539) +++ nagioscore/trunk/base/utils.c 2012-12-19 16:51:38 UTC (rev 2540) @@ -1777,6 +1777,17 @@ umask(S_IWGRP | S_IWOTH); + /* close existing stdin, stdout, stderr */ + close(0); + close(1); + close(2); + + /* THIS HAS TO BE DONE TO AVOID PROBLEMS WITH STDERR BEING REDIRECTED TO SERVICE MESSAGE PIPE! */ + /* re-open stdin, stdout, stderr with known values */ + open("/dev/null", O_RDONLY); + open("/dev/null", O_WRONLY); + open("/dev/null", O_WRONLY); + lockfile = open(lock_file, O_RDWR | O_CREAT, S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH); if(lockfile < 0) { @@ -1859,17 +1870,6 @@ val |= FD_CLOEXEC; fcntl(lockfile, F_SETFD, val); - /* close existing stdin, stdout, stderr */ - close(0); - close(1); - close(2); - - /* THIS HAS TO BE DONE TO AVOID PROBLEMS WITH STDERR BEING REDIRECTED TO SERVICE MESSAGE PIPE! */ - /* re-open stdin, stdout, stderr with known values */ - open("/dev/null", O_RDONLY); - open("/dev/null", O_WRONLY); - open("/dev/null", O_WRONLY); - #ifdef USE_EVENT_BROKER /* send program data to broker */ broker_program_state(NEBTYPE_PROCESS_DAEMONIZE, NEBFLAG_NONE, NEBATTR_NONE, NULL); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |