Beispiel #1
0
CNetBackend::CNetBackend()
{
    m_online_sockets = 0;
    m_tcp_sockets.assign( DEFAULT_SOCKETS,null );
    m_plistenning_socket = new CListenSocket();
    loop = EV_DEFAULT; //EV_DEFAULT每次返回的对象是同一个,相当于单例

    ev_set_syserr_cb( abort_work );
}
Beispiel #2
0
/**
 * @brief Initialise the clients-handling code
 */
void clients_init()
{
    clients_list = g_ptr_array_new();

    clients_list_lock = g_mutex_new();
    client_threads = g_thread_pool_new(client_loop, NULL,
                                       -1, /** @TODO link it to the max number of clients */
                                       false, NULL);

    ev_set_syserr_cb(libev_syserr);

#ifndef TLS
    if ( pthread_key_create(&client_ev_init_errors_key, NULL) ) {
        perror("pthread_key_create");
        exit(1);
    }
#endif
}
Beispiel #3
0
void
poller_init(void)
{
    ev_idle *idle = &eidle;
    ev_timer *timer = &etimer;
    ev_prepare *prepare = &eprepare;
    ev_check *check = &echeck;

    the_loop = ev_loop_new(EVFLAG_NOSIGMASK);
    //CTRACE("v %d.%d", ev_version_major(), ev_version_minor());
    //CTRACE("ev_supported_backends=%08x", ev_supported_backends());
    //CTRACE("ev_recommended_backends=%08x", ev_recommended_backends());
    //CTRACE("ev_embeddable_backends=%08x", ev_embeddable_backends());
    //CTRACE("ev_backend=%08x", ev_backend(the_loop));
#if EV_MULTIPLICITY
    //CTRACE("ev_now=%lf", ev_now(the_loop));
#else
    //CTRACE("ev_now=%lf", ev_now());
#endif
    ev_now_update(the_loop);
    timecounter_now = (uint64_t)(ev_now(the_loop) * 1000000000.);

    ev_idle_init(idle, _idle_cb);
    ev_timer_init(timer, _timer_cb, 0.0, 0.0);
    ev_timer_again(the_loop, timer);
    ev_prepare_init(prepare, _prepare_cb);
    ev_prepare_start(the_loop, prepare);
    ev_check_init(check, _check_cb);
    ev_check_start(the_loop, check);
    ev_set_syserr_cb(_syserr_cb);

    hash_init(&events,
              65521,
              (hash_hashfn_t)ev_item_hash,
              (hash_item_comparator_t)ev_item_cmp,
              (hash_item_finalizer_t)ev_item_fini);
}
Beispiel #4
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);
    }
}
Beispiel #5
0
/* pyev_module initialization */
PyObject *
init_pyev(void)
{
    PyObject *pyev;

#ifdef MS_WINDOWS
    if (pyev_setmaxstdio() || pyev_import_socket()) {
        return NULL;
    }
#endif
    /* fill in deferred data addresses */
    WatcherType.tp_new = PyType_GenericNew;
#if EV_PERIODIC_ENABLE
    PeriodicBaseType.tp_base = &WatcherType;
#endif
#if EV_STAT_ENABLE
    /* init StatdataType */
    if (!StatdataType_initialized) {
        PyStructSequence_InitType(&StatdataType, &Statdata_desc);
        StatdataType_initialized = 1;
    }
#endif
    /* pyev */
#if PY_MAJOR_VERSION >= 3
    pyev = PyModule_Create(&pyev_module);
#else
    pyev = Py_InitModule3("pyev", pyev_m_methods, pyev_m_doc);
#endif
    if (!pyev) {
        return NULL;
    }
    /* pyev.Error */
    Error = PyErr_NewException("pyev.Error", NULL, NULL);
    if (!Error || PyModule_AddObject(pyev, "Error", Error)) {
        Py_XDECREF(Error);
        goto fail;
    }
    /* adding types and constants */
    if (
        /* Loop */
        PyModule_AddType(pyev, "Loop", &LoopType) ||
        PyModule_AddUnsignedIntMacro(pyev, EVFLAG_AUTO) ||
        PyModule_AddUnsignedIntMacro(pyev, EVFLAG_NOENV) ||
        PyModule_AddUnsignedIntMacro(pyev, EVFLAG_FORKCHECK) ||
        PyModule_AddUnsignedIntMacro(pyev, EVFLAG_NOINOTIFY) ||
        PyModule_AddUnsignedIntMacro(pyev, EVFLAG_SIGNALFD) ||
        PyModule_AddUnsignedIntMacro(pyev, EVFLAG_NOSIGMASK) ||
        PyModule_AddUnsignedIntMacro(pyev, EVBACKEND_SELECT) ||
        PyModule_AddUnsignedIntMacro(pyev, EVBACKEND_POLL) ||
        PyModule_AddUnsignedIntMacro(pyev, EVBACKEND_EPOLL) ||
        PyModule_AddUnsignedIntMacro(pyev, EVBACKEND_KQUEUE) ||
        PyModule_AddUnsignedIntMacro(pyev, EVBACKEND_DEVPOLL) ||
        PyModule_AddUnsignedIntMacro(pyev, EVBACKEND_PORT) ||
        PyModule_AddUnsignedIntMacro(pyev, EVBACKEND_ALL) ||
        PyModule_AddUnsignedIntMacro(pyev, EVBACKEND_MASK) ||
        PyModule_AddIntMacro(pyev, EVRUN_NOWAIT) ||
        PyModule_AddIntMacro(pyev, EVRUN_ONCE) ||
        PyModule_AddIntMacro(pyev, EVBREAK_ONE) ||
        PyModule_AddIntMacro(pyev, EVBREAK_ALL) ||
        /* watchers */
        PyType_Ready(&WatcherType) ||
        PyModule_AddWatcher(pyev, "Io", &IoType, NULL) ||
        PyModule_AddIntMacro(pyev, EV_IO) ||
        PyModule_AddIntMacro(pyev, EV_READ) ||
        PyModule_AddIntMacro(pyev, EV_WRITE) ||
        PyModule_AddWatcher(pyev, "Timer", &TimerType, NULL) ||
        PyModule_AddIntMacro(pyev, EV_TIMER) ||
#if EV_PERIODIC_ENABLE
        PyType_Ready(&PeriodicBaseType) ||
        PyModule_AddWatcher(pyev, "Periodic", &PeriodicType,
                            &PeriodicBaseType) ||
        PyModule_AddIntMacro(pyev, EV_PERIODIC) ||
#if EV_PREPARE_ENABLE
        PyModule_AddWatcher(pyev, "Scheduler", &SchedulerType,
                            &PeriodicBaseType) ||
#endif
#endif
#if EV_SIGNAL_ENABLE
        PyModule_AddWatcher(pyev, "Signal", &SignalType, NULL) ||
        PyModule_AddIntMacro(pyev, EV_SIGNAL) ||
#endif
#if EV_CHILD_ENABLE
        PyModule_AddWatcher(pyev, "Child", &ChildType, NULL) ||
        PyModule_AddIntMacro(pyev, EV_CHILD) ||
#endif
#if EV_STAT_ENABLE
        PyModule_AddWatcher(pyev, "Stat", &StatType, NULL) ||
        PyModule_AddIntMacro(pyev, EV_STAT) ||
#endif
#if EV_IDLE_ENABLE
        PyModule_AddWatcher(pyev, "Idle", &IdleType, NULL) ||
        PyModule_AddIntMacro(pyev, EV_IDLE) ||
#endif
#if EV_PREPARE_ENABLE
        PyModule_AddWatcher(pyev, "Prepare", &PrepareType, NULL) ||
        PyModule_AddIntMacro(pyev, EV_PREPARE) ||
#endif
#if EV_CHECK_ENABLE
        PyModule_AddWatcher(pyev, "Check", &CheckType, NULL) ||
        PyModule_AddIntMacro(pyev, EV_CHECK) ||
#endif
#if EV_EMBED_ENABLE
        PyModule_AddWatcher(pyev, "Embed", &EmbedType, NULL) ||
        PyModule_AddIntMacro(pyev, EV_EMBED) ||
#endif
#if EV_FORK_ENABLE
        PyModule_AddWatcher(pyev, "Fork", &ForkType, NULL) ||
        PyModule_AddIntMacro(pyev, EV_FORK) ||
#endif
#if EV_ASYNC_ENABLE
        PyModule_AddWatcher(pyev, "Async", &AsyncType, NULL) ||
        PyModule_AddIntMacro(pyev, EV_ASYNC) ||
#endif
        /* additional events */
        PyModule_AddIntMacro(pyev, EV_CUSTOM) ||
        PyModule_AddIntMacro(pyev, EV_ERROR) ||
        /* priorities */
        PyModule_AddIntMacro(pyev, EV_MINPRI) ||
        PyModule_AddIntMacro(pyev, EV_MAXPRI)
       ) {
        goto fail;
    }
    /* setup libev */
    ev_set_allocator(pyev_allocator);
    ev_set_syserr_cb(pyev_syserr_cb);
    return pyev;

fail:
#if PY_MAJOR_VERSION >= 3
    Py_DECREF(pyev);
#endif
    return NULL;
}
Beispiel #6
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);
}