Exemplo n.º 1
0
/**
 * Get/set the watcher priority.  If passed a new_priority, then the
 * old_priority will be returned.  Otherwise, just returns the current
 * priority.
 *
 * Usage:
 *   old_priority = watcher:priority([new_priority])
 *
 * [+1, -0, e]
 */
static int watcher_priority(lua_State *L) {
    int has_pri = lua_gettop(L) > 1;
    ev_watcher *w = check_watcher(L, 1);
    int old_pri = ev_priority(w);

#if LUA_VERSION_NUM > 502
    if ( has_pri ) ev_set_priority(w, (int)luaL_checkinteger(L, 2));
#else
    if ( has_pri ) ev_set_priority(w, luaL_checkint(L, 2));
#endif
    lua_pushinteger(L, old_pri);
    return 1;
}
Exemplo n.º 2
0
int main(int argc, char *argv[])
{
    if (0 != parse_options(argc, argv))
    {
        usage();
        return 1;
    }

    if (!verbose)
        log_setlevel(LOGLEVEL_CRITICAL);

    memset(&g_srvctx, 0, sizeof(g_srvctx));
    g_srvctx.loop = ev_default_loop(0);
    ev_set_userdata(g_srvctx.loop, &g_srvctx);

    if (NULL == (g_srvctx.timer_1hz = (struct ev_timer *)malloc(sizeof(struct ev_timer))))
        LOG_CRITICAL("out of mem");
    if (NULL == (g_srvctx.timer_10hz = (struct ev_timer *)malloc(sizeof(struct ev_timer))))
        LOG_CRITICAL("out of mem");
    if (NULL == (g_srvctx.idle_watcher = (struct ev_idle *)malloc(sizeof(struct ev_idle))))
        LOG_CRITICAL("out of mem");

    ev_timer_init(g_srvctx.timer_1hz, (void *)timeout_1hz_cb, 0, 1);
    ev_set_priority(g_srvctx.timer_1hz, EV_MAXPRI);
    ev_timer_start(g_srvctx.loop, g_srvctx.timer_1hz);
    ev_timer_init(g_srvctx.timer_10hz, (void *)timeout_10hz_cb, 0, 0.1);
    ev_set_priority(g_srvctx.timer_10hz, EV_MAXPRI);
    ev_timer_start(g_srvctx.loop, g_srvctx.timer_10hz);
    ev_idle_init(g_srvctx.idle_watcher, idle_cb);

    if (0 != serial_init(g_srvctx.loop, &(g_srvctx.serialctx), device_name))
    {
        LOG_CRITICAL("Failed to open %s", device_name);
    }

    if (0 != mqtt_connect(&(g_srvctx.mqttctx), CLIENT_NAME, server, port))
    {
        LOG_CRITICAL("failed to connect to server");
    }

    while(1)
    {
        ev_loop(g_srvctx.loop, 0);
    }

    return 0;
}
Exemplo n.º 3
0
/**
 * Get/set the watcher priority.  If passed a new_priority, then the
 * old_priority will be returned.  Otherwise, just returns the current
 * priority.
 *
 * Usage:
 *   old_priority = watcher:priority([new_priority])
 *
 * [+1, -0, e]
 */
static int watcher_priority(lua_State *L) {
    int has_pri = lua_gettop(L) > 1;
    ev_watcher *w = check_watcher(L, 1);
    int old_pri = ev_priority(w);

    if ( has_pri ) ev_set_priority(w, luaL_checkint(L, 2));
    lua_pushinteger(L, old_pri);
    return 1;
}
Exemplo n.º 4
0
Arquivo: core.c Projeto: ifzz/lem
static int
signal_os_watch(lua_State *T, int sig)
{
	struct sigwatcher *s;

	if (sigismember(&signal_sigset, sig))
		goto out; /* already watched */

	s = lem_xmalloc(sizeof(struct sigwatcher));

	signal_watcher_init(s, sig);
	ev_set_priority(&s->w, EV_MAXPRI);
	ev_signal_start(LEM_ &s->w);
	ev_unref(LEM); /* watcher shouldn't keep loop alive */

	sigaddset(&signal_sigset, sig);
	pthread_sigmask(SIG_UNBLOCK, &signal_sigset, NULL);

	s->next = signal_watchers;
	signal_watchers = s;
out:
	lua_pushboolean(T, 1);
	return 1;
}
Exemplo n.º 5
0
int main(int argc, char** argv) {
    // Bail out early if we don't have the right argument
    //   count, and try to tell the user not to run us
    //   if stderr happens to be hooked up to a terminal
    if(argc != 5) {
        fprintf(stderr, "This binary is not for human execution!\n");
        exit(99);
    }

    bool debug = false;
    if(!strcmp(argv[1], "Y"))
        debug = true;

    bool use_syslog = false;
    if(!strcmp(argv[2], "S"))
        use_syslog = true;

    dmn_init1(debug, true, use_syslog, "gdnsd_extmon_helper");
    // Note that gdnsd_initialize() would be standard here, but extmon_helper
    // is special: it doesn't actually make use of most of libgdnsd, just the
    // very basic compiler, allocator, and libdmn logging bits.

    // regardless, we seal off stdin now.  We don't need it,
    //   and this way we don't have to deal with it when
    //   execv()-ing child commands later.
    if(!freopen("/dev/null", "r", stdin))
        dmn_log_fatal("Cannot open /dev/null: %s", dmn_logf_strerror(errno));

    // Also unconditionally unset NOTIFY_SOCKET here so that children
    //   don't get any ideas about talking to systemd on our behalf.
    //   (we're done using it in this process for libdmn stuff at this point)
    unsetenv("NOTIFY_SOCKET");

    // these are the main communication pipes to the daemon/plugin
    plugin_read_fd = atoi(argv[3]);
    plugin_write_fd = atoi(argv[4]);

    if(plugin_read_fd < 3 || plugin_read_fd > 1000
        || plugin_write_fd < 3 || plugin_write_fd > 1000)
        log_fatal("Invalid pipe descriptors!");

    if(emc_read_exact(plugin_read_fd, "HELO"))
        log_fatal("Failed to read HELO from plugin");
    if(emc_write_string(plugin_write_fd, "HELO_ACK", 8))
        log_fatal("Failed to write HELO_ACK to plugin");

    uint8_t ccount_buf[7];
    if(emc_read_nbytes(plugin_read_fd, 7, ccount_buf)
        || strncmp((char*)ccount_buf, "CMDS:", 5))
        log_fatal("Failed to read command count from plugin");
    num_mons = ((unsigned)ccount_buf[5] << 8) + ccount_buf[6];
    if(!num_mons)
        log_fatal("Received command count of zero from plugin");
    mons = xcalloc(num_mons, sizeof(mon_t));

    if(emc_write_string(plugin_write_fd, "CMDS_ACK", 8))
        log_fatal("Failed to write CMDS_ACK to plugin");

    // Note, it's merely a happy coincidence that our mons[]
    //   indices exactly match cmd->idx numbers.  Always use
    //   the cmd->idx numbers as the official index when talking
    //   to the main daemon!
    for(unsigned i = 0; i < num_mons; i++) {
        mons[i].cmd = emc_read_command(plugin_read_fd);
        if(!mons[i].cmd)
            log_fatal("Failed to read command %u from plugin", i);
        if(i != mons[i].cmd->idx)
            log_fatal("BUG: plugin index issues, %u vs %u", i, mons[i].cmd->idx);
        if(emc_write_string(plugin_write_fd, "CMD_ACK", 7))
            log_fatal("Failed to write CMD_ACK for command %u to plugin", i);
    }

    if(emc_read_exact(plugin_read_fd, "END_CMDS"))
        log_fatal("Failed to read END_CMDS from plugin");
    if(emc_write_string(plugin_write_fd, "END_CMDS_ACK", 12))
        log_fatal("Failed to write END_CMDS_ACK to plugin");

    // done with the serial setup, close the readpipe and go nonblocking on write for eventloop...
    close(plugin_read_fd);
    if(fcntl(plugin_write_fd, F_SETFL, (fcntl(plugin_write_fd, F_GETFL, 0)) | O_NONBLOCK) == -1)
        log_fatal("Failed to set O_NONBLOCK on pipe: %s", dmn_logf_errno());

    // CLOEXEC the write fd so child scripts can't mess with it
    if(fcntl(plugin_write_fd, F_SETFD, FD_CLOEXEC))
        log_fatal("Failed to set FD_CLOEXEC on plugin write fd: %s", dmn_logf_strerror(errno));

    // init results-sending queue
    sendq_init();

    // Set up libev error callback
    ev_set_syserr_cb(&syserr_for_ev);

    // Construct the default loop for the main thread
    struct ev_loop* def_loop = ev_default_loop(EVFLAG_AUTO);
    if(!def_loop) log_fatal("Could not initialize the default libev loop");

    // Catch SIGINT/TERM/HUP, and do not let them prevent loop exit
    sigterm_watcher = xmalloc(sizeof(ev_signal));
    sigint_watcher = xmalloc(sizeof(ev_signal));
    sighup_watcher = xmalloc(sizeof(ev_signal));
    ev_signal_init(sigterm_watcher, sig_cb, SIGTERM);
    ev_signal_init(sigint_watcher, sig_cb, SIGINT);
    ev_signal_init(sighup_watcher, sig_cb, SIGHUP);
    ev_signal_start(def_loop, sigterm_watcher);
    ev_signal_start(def_loop, sigint_watcher);
    ev_signal_start(def_loop, sighup_watcher);
    ev_unref(def_loop);
    ev_unref(def_loop);
    ev_unref(def_loop);

    // set up primary read/write watchers on the pipe to the daemon's plugin
    plugin_write_watcher = xmalloc(sizeof(ev_io));
    ev_io_init(plugin_write_watcher, plugin_write_cb, plugin_write_fd, EV_WRITE);
    ev_set_priority(plugin_write_watcher, 1);

    // set up interval watchers for each monitor, initially for immediate firing
    //   for the daemon's monitoring init cycle, then repeating every interval.
    for(unsigned i = 0; i < num_mons; i++) {
        mon_t* this_mon = &mons[i];
        this_mon->interval_timer = xmalloc(sizeof(ev_timer));
        ev_timer_init(this_mon->interval_timer, mon_interval_cb, 0., this_mon->cmd->interval);
        this_mon->interval_timer->data = this_mon;
        ev_set_priority(this_mon->interval_timer, 0);
        ev_timer_start(def_loop, this_mon->interval_timer);

        // initialize the other watchers in the mon_t here as well,
        //   but do not start them (the interval callback starts them each interval)
        this_mon->cmd_timeout = xmalloc(sizeof(ev_timer));
        ev_timer_init(this_mon->cmd_timeout, mon_timeout_cb, 0, 0);
        ev_set_priority(this_mon->cmd_timeout, -1);
        this_mon->cmd_timeout->data = this_mon;

        this_mon->child_watcher = xmalloc(sizeof(ev_child));
        ev_child_init(this_mon->child_watcher, mon_child_cb, 0, 0);
        this_mon->child_watcher->data = this_mon;
    }

    log_info("gdnsd_extmon_helper running");
    ev_run(def_loop, 0);

    // graceful shutdown should have cleared out children, but
    // the hard kill/wait below is for (a) ungraceful shutdown
    // on unexpected pipe close and (b) anything else going wrong
    // during graceful shutdown.
    bool needs_wait = false;
    for(unsigned i = 0; i < num_mons; i++) {
        if(mons[i].cmd_pid) {
            log_debug("not-so-graceful shutdown: sending SIGKILL to %li", (long)mons[i].cmd_pid);
            kill(mons[i].cmd_pid, SIGKILL);
            needs_wait = true;
        }
    }

    if(needs_wait) {
        unsigned i = 500; // 5s for OS to give us all the SIGKILL'd zombies
        while(i--) {
            pid_t wprv = waitpid(-1, NULL, WNOHANG);
            if(wprv < 0) {
                if(errno == ECHILD)
                    break;
                else
                    log_fatal("waitpid(-1, NULL, WNOHANG) failed: %s", dmn_logf_errno());
            }
            if(wprv)
                log_debug("not-so-graceful shutdown: waitpid reaped %li", (long)wprv);
            const struct timespec ms_10 = { 0, 10000000 };
            nanosleep(&ms_10, NULL);
        }
    }

    // Bye!
    if(killed_by) {
        log_info("gdnsd_extmon_helper exiting gracefully due to signal %i", killed_by);
#ifdef COVERTEST_EXIT
        exit(0);
#else
        raise(killed_by);
#endif
    }
    else {
        log_info("gdnsd_extmon_helper exiting un-gracefully");
        exit(42);
    }
}
Exemplo n.º 6
0
 AcceptEvent(int fd, const std::function<void()> &cb) : callback(cb){
   struct ev_loop *loop = EV_DEFAULT;
   ev_io_init(&event, &AcceptEvent::trampoline, fd, EV_READ);
   ev_set_priority(&event, 1); // Higher priority than normal
   ev_io_start(EV_A_ &event);
 }
Exemplo n.º 7
0
int main(int argc, char** argv) {
    dmn_init_log("gdnsd_extmon_helper", true);

    // start up syslog IFF it appears the daemon
    //   was *not* started via "startfg".  Regular
    //   start/restart would have /dev/null'd the
    //   standard descriptors before forking us off.
    if(!isatty(0))
        dmn_start_syslog();

    // Bail out early if we don't have the right argument
    //   count, and try to tell the user not to run us
    //   if stderr happens to be hooked up to a terminal
    if(argc != 5) {
        fprintf(stderr, "This binary is not for human execution!\n");
        abort();
    }

    // open stderr logging connection using passed fd
    dmn_log_set_alt_stderr(atoi(argv[2]));

    // regardless, we seal off stdin now.  We don't need it,
    //   and this way we don't have to deal with it when
    //   execv()-ing child commands later.
    if(!freopen("/dev/null", "r", stdin))
        dmn_log_fatal("Cannot open /dev/null: %s", dmn_strerror(errno));

    if(!strcmp(argv[1], "Y"))
        dmn_set_debug(true);
    else if(!strcmp(argv[1], "N"))
        dmn_set_debug(false);
    else
        log_fatal("Invalid debug argument on cmdline: '%s'!", argv[1]);

    // these are the main communication pipes to the daemon/plugin
    plugin_read_fd = atoi(argv[3]);
    plugin_write_fd = atoi(argv[4]);

    if(plugin_read_fd < 3 || plugin_read_fd > 1000
        || plugin_write_fd < 3 || plugin_write_fd > 1000)
        log_fatal("Invalid pipe descriptors!");

    // CLOEXEC the direct lines to the main plugin/daemon,
    //   so that child scripts can't screw with them.
    if(fcntl(plugin_read_fd, F_SETFD, FD_CLOEXEC))
        log_fatal("Failed to set FD_CLOEXEC on plugin read fd: %s", dmn_strerror(errno));
    if(fcntl(plugin_write_fd, F_SETFD, FD_CLOEXEC))
        log_fatal("Failed to set FD_CLOEXEC on plugin write fd: %s", dmn_strerror(errno));

    if(emc_read_exact(plugin_read_fd, "HELO"))
        log_fatal("Failed to read HELO from plugin");
    if(emc_write_string(plugin_write_fd, "HELO_ACK", 8))
        log_fatal("Failed to write HELO_ACK to plugin");

    uint8_t ccount_buf[7];
    if(emc_read_nbytes(plugin_read_fd, 7, ccount_buf)
        || strncmp((char*)ccount_buf, "CMDS:", 5))
        log_fatal("Failed to read command count from plugin");
    num_mons = ((unsigned)ccount_buf[5] << 8) + ccount_buf[6];
    if(!num_mons)
        log_fatal("Received command count of zero from plugin");
    mons = calloc(num_mons, sizeof(mon_t));

    if(emc_write_string(plugin_write_fd, "CMDS_ACK", 8))
        log_fatal("Failed to write CMDS_ACK to plugin");

    // Note, it's merely a happy coincidence that our mons[]
    //   indices exactly match cmd->idx numbers.  Always use
    //   the cmd->idx numbers as the official index when talking
    //   to the main daemon!
    for(unsigned i = 0; i < num_mons; i++) {
        mons[i].cmd = emc_read_command(plugin_read_fd);
        if(!mons[i].cmd)
            log_fatal("Failed to read command %u from plugin", i);
        if(i != mons[i].cmd->idx)
            log_fatal("BUG: plugin index issues, %u vs %u", i, mons[i].cmd->idx);
        if(emc_write_string(plugin_write_fd, "CMD_ACK", 7))
            log_fatal("Failed to write CMD_ACK for command %u to plugin", i);
    }

    if(emc_read_exact(plugin_read_fd, "END_CMDS"))
        log_fatal("Failed to read END_CMDS from plugin");
    if(emc_write_string(plugin_write_fd, "END_CMDS_ACK", 12))
        log_fatal("Failed to write END_CMDS_ACK to plugin");

    // done with the serial setup, close the readpipe and go nonblocking on write for eventloop...
    close(plugin_read_fd);
    if(unlikely(fcntl(plugin_write_fd, F_SETFL, (fcntl(plugin_write_fd, F_GETFL, 0)) | O_NONBLOCK) == -1))
        log_fatal("Failed to set O_NONBLOCK on pipe: %s", logf_errno());

    // init results-sending queue
    sendq_init();

    // Set up libev error callback
    ev_set_syserr_cb(&syserr_for_ev);

    // Construct the default loop for the main thread
    struct ev_loop* def_loop = ev_default_loop(EVFLAG_AUTO);
    if(!def_loop) log_fatal("Could not initialize the default libev loop");
    ev_set_timeout_collect_interval(def_loop, 0.1);
    ev_set_io_collect_interval(def_loop, 0.01);

    // set up primary read/write watchers on the pipe to the daemon's plugin
    plugin_read_watcher = malloc(sizeof(ev_io));
    plugin_write_watcher = malloc(sizeof(ev_io));
    ev_io_init(plugin_write_watcher, plugin_write_cb, plugin_write_fd, EV_WRITE);
    ev_set_priority(plugin_write_watcher, 1);

    // set up interval watchers for each monitor, initially for immediate firing
    //   for the daemon's monitoring init cycle, then repeating every interval.
    for(unsigned i = 0; i < num_mons; i++) {
        mon_t* this_mon = &mons[i];
        this_mon->interval_timer = malloc(sizeof(ev_timer));
        ev_timer_init(this_mon->interval_timer, mon_interval_cb, 0., this_mon->cmd->interval);
        this_mon->interval_timer->data = this_mon;
        ev_set_priority(this_mon->interval_timer, 0);
        ev_timer_start(def_loop, this_mon->interval_timer);

        // initialize the other watchers in the mon_t here as well,
        //   but do not start them (the interval callback starts them each interval)
        this_mon->cmd_timeout = malloc(sizeof(ev_timer));
        ev_timer_init(this_mon->cmd_timeout, mon_timeout_cb, 0, 0);
        ev_set_priority(this_mon->cmd_timeout, -1);
        this_mon->cmd_timeout->data = this_mon;

        this_mon->child_watcher = malloc(sizeof(ev_child));
        ev_child_init(this_mon->child_watcher, mon_child_cb, 0, 0);
        this_mon->child_watcher->data = this_mon;
    }

    log_info("gdnsd_extmon_helper running");

    // shut off stderr output from here out...
    dmn_log_close_alt_stderr();

    ev_run(def_loop, 0);
    log_info("gdnsd_extmon_helper terminating");

    // kill -9 on any extant child procs
    for(unsigned i = 0; i < num_mons; i++)
        if(mons[i].cmd_pid)
            kill(mons[i].cmd_pid, SIGKILL);

    // Bye!
    exit(0);
}