int mtev_main(const char *appname, const char *config_filename, int debug, int foreground, mtev_lock_op_t lock, const char *_glider, const char *drop_to_user, const char *drop_to_group, int (*passed_child_main)(void)) { mtev_conf_section_t watchdog_conf; int fd, lockfd, watchdog_timeout = 0, rv; int wait_for_lock; char conf_str[1024]; char lockfile[PATH_MAX]; char *trace_dir = NULL; char appscratch[1024]; char *glider = (char *)_glider; char *watchdog_timeout_str; int retry_val; int span_val; int ret; int cnt; mtev_conf_section_t root; wait_for_lock = (lock == MTEV_LOCK_OP_WAIT) ? 1 : 0; mtev_init_globals(); char *require_invariant_tsc = getenv("MTEV_RDTSC_REQUIRE_INVARIANT"); if (require_invariant_tsc && strcmp(require_invariant_tsc, "0") == 0) { mtev_time_toggle_require_invariant_tsc(mtev_false); } char *disable_rdtsc = getenv("MTEV_RDTSC_DISABLE"); if (disable_rdtsc && strcmp(disable_rdtsc, "1") == 0) { mtev_time_toggle_tsc(mtev_false); } char *disable_binding = getenv("MTEV_THREAD_BINDING_DISABLE"); if (disable_binding && strcmp(disable_binding, "1") == 0) { mtev_thread_disable_binding(); } /* First initialize logging, so we can log errors */ mtev_log_init(debug); mtev_log_stream_add_stream(mtev_debug, mtev_stderr); mtev_log_stream_add_stream(mtev_error, mtev_stderr); mtev_log_stream_add_stream(mtev_notice, mtev_error); /* Next load the configs */ mtev_conf_use_namespace(appname); mtev_conf_init(appname); if(mtev_conf_load(config_filename) == -1) { fprintf(stderr, "Cannot load config: '%s'\n", config_filename); exit(-1); } char* root_section_path = alloca(strlen(appname)+2); sprintf(root_section_path, "/%s", appname); root = mtev_conf_get_sections(NULL, root_section_path, &cnt); free(root); if(cnt==0) { fprintf(stderr, "The config must have <%s> as its root node\n", appname); exit(-1); } /* Reinitialize the logging system now that we have a config */ mtev_conf_log_init(appname, drop_to_user, drop_to_group); if(debug) { mtev_log_stream_set_flags(mtev_debug, mtev_log_stream_get_flags(mtev_debug) | MTEV_LOG_STREAM_ENABLED); } cli_log_switches(); snprintf(appscratch, sizeof(appscratch), "/%s/watchdog|/%s/include/watchdog", appname, appname); watchdog_conf = mtev_conf_get_section(NULL, appscratch); if(!glider) (void) mtev_conf_get_string(watchdog_conf, "@glider", &glider); if(mtev_watchdog_glider(glider)) { mtevL(mtev_stderr, "Invalid glider, exiting.\n"); exit(-1); } (void)mtev_conf_get_string(watchdog_conf, "@tracedir", &trace_dir); if(trace_dir) { if(mtev_watchdog_glider_trace_dir(trace_dir)) { mtevL(mtev_stderr, "Invalid glider tracedir, exiting.\n"); exit(-1); } } ret = mtev_conf_get_int(watchdog_conf, "@retries", &retry_val); if((ret == 0) || (retry_val == 0)) { retry_val = 5; } ret = mtev_conf_get_int(watchdog_conf, "@span", &span_val); if((ret == 0) || (span_val == 0)) { span_val = 60; } mtev_watchdog_ratelimit(retry_val, span_val); /* Lastly, run through all other system inits */ snprintf(appscratch, sizeof(appscratch), "/%s/eventer/@implementation", appname); if(!mtev_conf_get_stringbuf(NULL, appscratch, conf_str, sizeof(conf_str))) { mtevL(mtev_stderr, "Cannot find '%s' in configuration\n", appscratch); exit(-1); } if(eventer_choose(conf_str) == -1) { mtevL(mtev_stderr, "Cannot choose eventer %s\n", conf_str); exit(-1); } if(configure_eventer(appname) != 0) { mtevL(mtev_stderr, "Cannot configure eventer\n"); exit(-1); } mtev_watchdog_prefork_init(); if(foreground != 1 && chdir("/") != 0) { mtevL(mtev_stderr, "Failed chdir(\"/\"): %s\n", strerror(errno)); exit(-1); } /* Acquire the lock so that we can throw an error if it doesn't work. * If we've started -D, we'll have the lock. * If not we will daemon and must reacquire the lock. */ lockfd = -1; lockfile[0] = '\0'; snprintf(appscratch, sizeof(appscratch), "/%s/@lockfile", appname); if(lock != MTEV_LOCK_OP_NONE && mtev_conf_get_stringbuf(NULL, appscratch, lockfile, sizeof(lockfile))) { do { if((lockfd = mtev_lockfile_acquire(lockfile)) < 0) { if(!wait_for_lock) { mtevL(mtev_stderr, "Failed to acquire lock: %s\n", lockfile); exit(-1); } if(wait_for_lock == 1) { mtevL(mtev_stderr, "%d failed to acquire lock(%s), waiting...\n", (int)getpid(), lockfile); wait_for_lock++; } usleep(1000); } else { if(wait_for_lock > 1) mtevL(mtev_stderr, "Lock acquired proceeding.\n"); wait_for_lock = 0; } } while(wait_for_lock); } if(foreground == 1) { mtev_time_start_tsc(); mtevL(mtev_notice, "%s booting [unmanaged]\n", appname); int rv = passed_child_main(); mtev_lockfile_release(lockfd); return rv; } watchdog_timeout_str = getenv("WATCHDOG_TIMEOUT"); if(watchdog_timeout_str) { watchdog_timeout = atoi(watchdog_timeout_str); mtevL(mtev_error, "Setting watchdog timeout to %d\n", watchdog_timeout); } /* This isn't inherited across forks... */ if(lockfd >= 0) mtev_lockfile_release(lockfd); lockfd = -1; if(foreground == 0) { fd = open("/dev/null", O_RDONLY); if(fd < 0 || dup2(fd, STDIN_FILENO) < 0) { fprintf(stderr, "Failed to setup stdin: %s\n", strerror(errno)); exit(-1); } close(fd); fd = open("/dev/null", O_WRONLY); if(fd < 0 || dup2(fd, STDOUT_FILENO) < 0 || dup2(fd, STDERR_FILENO) < 0) { fprintf(stderr, "Failed to setup std{out,err}: %s\n", strerror(errno)); exit(-1); } close(fd); if(fork()) exit(0); setsid(); if(fork()) exit(0); } /* Reacquire the lock */ if(*lockfile) { if (lock) { if((lockfd = mtev_lockfile_acquire(lockfile)) < 0) { mtevL(mtev_stderr, "Failed to acquire lock: %s\n", lockfile); exit(-1); } } } signal(SIGHUP, SIG_IGN); mtevL(mtev_notice, "%s booting\n", appname); rv = mtev_watchdog_start_child(appname, passed_child_main, watchdog_timeout); mtev_lockfile_release(lockfd); return rv; }
int main(int argc, char **argv) { int fd, lockfd = -1; char lockfile[PATH_MAX]; char user[32], group[32]; char *trace_dir = NULL; parse_clargs(argc, argv); noit_log_init(); noit_log_stream_add_stream(noit_debug, noit_stderr); noit_log_stream_add_stream(noit_error, noit_stderr); /* Next load the configs */ noit_conf_init(APPNAME); if(noit_conf_load(config_file) == -1) { fprintf(stderr, "Cannot load config: '%s'\n", config_file); exit(-1); } /* Reinitialize the logging system now that we have a config */ snprintf(user, sizeof(user), "%d", getuid()); snprintf(group, sizeof(group), "%d", getgid()); if(noit_security_usergroup(droptouser, droptogroup, noit_true)) { noitL(noit_stderr, "Failed to drop privileges, exiting.\n"); exit(-1); } noit_conf_log_init(APPNAME); cli_log_switches(); if(noit_security_usergroup(user, group, noit_true)) { noitL(noit_stderr, "Failed to regain privileges, exiting.\n"); exit(-1); } if(debug) noit_debug->enabled = 1; if(!glider) noit_conf_get_string(NULL, "/" APPNAME "/watchdog/@glider", &glider); noit_watchdog_glider(glider); noit_conf_get_string(NULL, "/" APPNAME "/watchdog/@tracedir", &trace_dir); if(trace_dir) noit_watchdog_glider_trace_dir(trace_dir); if(chdir("/") != 0) { fprintf(stderr, "cannot chdir(\"/\"): %s\n", strerror(errno)); exit(2); } noit_watchdog_prefork_init(); /* Acquire the lock so that we can throw an error if it doesn't work. * If we've started -D, we'll have the lock. * If not we will daemon and must reacquire the lock. */ lockfd = -1; lockfile[0] = '\0'; if(noit_conf_get_stringbuf(NULL, "/" APPNAME "/@lockfile", lockfile, sizeof(lockfile))) { if((lockfd = noit_lockfile_acquire(lockfile)) < 0) { noitL(noit_stderr, "Failed to acquire lock: %s\n", lockfile); exit(-1); } } if(foreground) exit(child_main()); /* This isn't inherited across forks... */ if(lockfd >= 0) noit_lockfile_release(lockfd); fd = open("/dev/null", O_RDWR); dup2(fd, STDIN_FILENO); dup2(fd, STDOUT_FILENO); dup2(fd, STDERR_FILENO); if(fork()) exit(0); setsid(); if(fork()) exit(0); /* Reacquire the lock */ if(*lockfile) { if(noit_lockfile_acquire(lockfile) < 0) { noitL(noit_stderr, "Failed to acquire lock: %s\n", lockfile); exit(-1); } } return noit_watchdog_start_child("stratcond", child_main, 0); }
int noit_main(const char *appname, const char *config_filename, int debug, int foreground, const char *_glider, const char *drop_to_user, const char *drop_to_group, int (*passed_child_main)(void)) { int fd, lockfd, watchdog_timeout = 0; char conf_str[1024]; char lockfile[PATH_MAX]; char user[32], group[32]; char *trace_dir = NULL; char appscratch[1024]; char *glider = (char *)_glider; char *watchdog_timeout_str; /* First initialize logging, so we can log errors */ noit_log_init(); noit_log_stream_add_stream(noit_debug, noit_stderr); noit_log_stream_add_stream(noit_error, noit_stderr); /* Next load the configs */ noit_conf_init(appname); if(noit_conf_load(config_filename) == -1) { fprintf(stderr, "Cannot load config: '%s'\n", config_filename); exit(-1); } /* Reinitialize the logging system now that we have a config */ snprintf(user, sizeof(user), "%d", getuid()); snprintf(group, sizeof(group), "%d", getgid()); if(noit_security_usergroup(drop_to_user, drop_to_group, noit_true)) { noitL(noit_stderr, "Failed to drop privileges, exiting.\n"); exit(-1); } noit_conf_log_init(appname); cli_log_switches(); if(noit_security_usergroup(user, group, noit_true)) { noitL(noit_stderr, "Failed to regain privileges, exiting.\n"); exit(-1); } if(debug) noit_debug->enabled = 1; snprintf(appscratch, sizeof(appscratch), "/%s/watchdog/@glider", appname); if(!glider) noit_conf_get_string(NULL, appscratch, &glider); noit_watchdog_glider(glider); snprintf(appscratch, sizeof(appscratch), "/%s/watchdog/@tracedir", appname); noit_conf_get_string(NULL, appscratch, &trace_dir); if(trace_dir) noit_watchdog_glider_trace_dir(trace_dir); /* Lastly, run through all other system inits */ snprintf(appscratch, sizeof(appscratch), "/%s/eventer/@implementation", appname); if(!noit_conf_get_stringbuf(NULL, appscratch, conf_str, sizeof(conf_str))) { noitL(noit_stderr, "Cannot find '%s' in configuration\n", appscratch); exit(-1); } if(eventer_choose(conf_str) == -1) { noitL(noit_stderr, "Cannot choose eventer %s\n", conf_str); exit(-1); } if(configure_eventer(appname) != 0) { noitL(noit_stderr, "Cannot configure eventer\n"); exit(-1); } noit_watchdog_prefork_init(); if(chdir("/") != 0) { noitL(noit_stderr, "Failed chdir(\"/\"): %s\n", strerror(errno)); exit(-1); } /* Acquire the lock so that we can throw an error if it doesn't work. * If we've started -D, we'll have the lock. * If not we will daemon and must reacquire the lock. */ lockfd = -1; lockfile[0] = '\0'; snprintf(appscratch, sizeof(appscratch), "/%s/@lockfile", appname); if(noit_conf_get_stringbuf(NULL, appscratch, lockfile, sizeof(lockfile))) { if((lockfd = noit_lockfile_acquire(lockfile)) < 0) { noitL(noit_stderr, "Failed to acquire lock: %s\n", lockfile); exit(-1); } } if(foreground) return passed_child_main(); watchdog_timeout_str = getenv("WATCHDOG_TIMEOUT"); if(watchdog_timeout_str) { watchdog_timeout = atoi(watchdog_timeout_str); noitL(noit_error, "Setting watchdog timeout to %d\n", watchdog_timeout); } /* This isn't inherited across forks... */ if(lockfd >= 0) noit_lockfile_release(lockfd); fd = open("/dev/null", O_RDWR); dup2(fd, STDIN_FILENO); dup2(fd, STDOUT_FILENO); dup2(fd, STDERR_FILENO); if(fork()) exit(0); setsid(); if(fork()) exit(0); /* Reacquire the lock */ if(*lockfile) { if(noit_lockfile_acquire(lockfile) < 0) { noitL(noit_stderr, "Failed to acquire lock: %s\n", lockfile); exit(-1); } } signal(SIGHUP, SIG_IGN); return noit_watchdog_start_child("noitd", passed_child_main, watchdog_timeout); }