Ejemplo n.º 1
0
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;
}
Ejemplo n.º 2
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);
}