static int signal_handler(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) {
        sd_event_source *p = NULL;
        sigset_t ss;
        pid_t pid;

        assert_se(s);
        assert_se(si);

        log_info("got signal on %c", PTR_TO_INT(userdata));

        assert_se(userdata == INT_TO_PTR('e'));

        assert_se(sigemptyset(&ss) >= 0);
        assert_se(sigaddset(&ss, SIGCHLD) >= 0);
        assert_se(sigprocmask(SIG_BLOCK, &ss, NULL) >= 0);

        pid = fork();
        assert_se(pid >= 0);

        if (pid == 0)
                _exit(0);

        assert_se(sd_event_add_child(sd_event_source_get_event(s), &p, pid, WEXITED, child_handler, INT_TO_PTR('f')) >= 0);
        assert_se(sd_event_source_set_enabled(p, SD_EVENT_ONESHOT) >= 0);

        sd_event_source_unref(s);

        return 1;
}
Ejemplo n.º 2
0
static int sntp_arm_timer(SNTPContext *sntp, usec_t next) {
        sd_event *e;
        int r;

        assert(sntp);
        assert(sntp->event_receive);

        if (next == 0) {
                sntp->event_timer = sd_event_source_unref(sntp->event_timer);
                return 0;
        }

        if (sntp->event_timer) {
                r = sd_event_source_set_time(sntp->event_timer, now(CLOCK_MONOTONIC) + next);
                if (r < 0)
                        return r;

                return sd_event_source_set_enabled(sntp->event_timer, SD_EVENT_ONESHOT);
        }

        e = sd_event_source_get_event(sntp->event_receive);
        r = sd_event_add_time(
                        e,
                        &sntp->event_timer,
                        CLOCK_MONOTONIC,
                        now(CLOCK_MONOTONIC) + next, 0,
                        sntp_timer, sntp);
        if (r < 0)
                return r;

        return 0;
}
Ejemplo n.º 3
0
static int on_lldp_timer(sd_event_source *s, usec_t t, void *userdata) {
        Link *link = userdata;
        usec_t current, delay, next;
        int r;

        assert(s);
        assert(userdata);

        log_link_debug(link, "Sending LLDP packet...");

        r = link_send_lldp(link);
        if (r < 0)
                log_link_debug_errno(link, r, "Failed to send LLDP packet, ignoring: %m");

        if (link->lldp_tx_fast > 0)
                link->lldp_tx_fast--;

        assert_se(sd_event_now(sd_event_source_get_event(s), clock_boottime_or_monotonic(), &current) >= 0);

        delay = link->lldp_tx_fast > 0 ? LLDP_FAST_TX_USEC : LLDP_TX_INTERVAL_USEC;
        next = usec_add(usec_add(current, delay), (usec_t) random_u64() % LLDP_JITTER_USEC);

        r = sd_event_source_set_time(s, next);
        if (r < 0)
                return log_link_error_errno(link, r, "Failed to restart LLDP timer: %m");

        r = sd_event_source_set_enabled(s, SD_EVENT_ONESHOT);
        if (r < 0)
                return log_link_error_errno(link, r, "Failed to enable LLDP timer: %m");

        return 0;
}
Ejemplo n.º 4
0
static int timerfd_handler(sd_event_source *s,
                           int fd,
                           uint32_t revents,
                           void *userdata) {
        ClockState *sp = userdata;

        return clock_state_update(sp, sd_event_source_get_event(s));
}
static int child_handler(sd_event_source *s, const siginfo_t *si, void *userdata) {

        assert_se(s);
        assert_se(si);

        log_info("got child on %c", PTR_TO_INT(userdata));

        assert_se(userdata == INT_TO_PTR('f'));

        assert_se(sd_event_exit(sd_event_source_get_event(s), 0) >= 0);
        sd_event_source_unref(s);

        return 1;
}
static int time_handler(sd_event_source *s, uint64_t usec, void *userdata) {
        log_info("got timer on %c", PTR_TO_INT(userdata));

        if (userdata == INT_TO_PTR('c')) {

                if (do_quit) {
                        sd_event_source *p;

                        assert_se(sd_event_add_defer(sd_event_source_get_event(s), &p, defer_handler, INT_TO_PTR('d')) >= 0);
                        assert_se(sd_event_source_set_enabled(p, SD_EVENT_ONESHOT) >= 0);
                } else {
                        assert_se(!got_c);
                        got_c = true;
                }
        } else
                assert_not_reached("Huh?");

        return 2;
}
Ejemplo n.º 7
0
static int defer_handler(sd_event_source *s, void *userdata) {
        sd_event_source *p = NULL;

        assert_se(s);

        log_info("got defer on %c", PTR_TO_INT(userdata));

        assert_se(userdata == INT_TO_PTR('d'));

        assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGUSR1, -1) >= 0);

        assert_se(sd_event_add_signal(sd_event_source_get_event(s), &p, SIGUSR1, signal_handler, INT_TO_PTR('e')) >= 0);
        assert_se(sd_event_source_set_enabled(p, SD_EVENT_ONESHOT) >= 0);
        raise(SIGUSR1);

        sd_event_source_unref(s);

        return 1;
}
Ejemplo n.º 8
0
static int inotify_handler(sd_event_source *s,
                           int fd,
                           uint32_t revents,
                           void *userdata) {
        sd_event *event = sd_event_source_get_event(s);
        ClockState *sp = userdata;
        union inotify_event_buffer buffer;
        struct inotify_event *e;
        ssize_t l;

        l = read(fd, &buffer, sizeof(buffer));
        if (l < 0) {
                if (IN_SET(errno, EAGAIN, EINTR))
                        return 0;

                return log_warning_errno(errno, "Lost access to inotify: %m");
        }
        FOREACH_INOTIFY_EVENT(e, buffer, l)
                process_inotify_event(event, sp, e);

        return 0;
}
Ejemplo n.º 9
0
/* wake up when the system time changes underneath us */
static int sntp_clock_watch_setup(SNTPContext *sntp) {
        struct itimerspec its = { .it_value.tv_sec = TIME_T_MAX };
        _cleanup_close_ int fd = -1;
        sd_event *e;
        sd_event_source *source;
        int r;

        assert(sntp);
        assert(sntp->event_receive);

        fd = timerfd_create(CLOCK_REALTIME, TFD_NONBLOCK|TFD_CLOEXEC);
        if (fd < 0) {
                log_error("Failed to create timerfd: %m");
                return -errno;
        }

        if (timerfd_settime(fd, TFD_TIMER_ABSTIME|TFD_TIMER_CANCEL_ON_SET, &its, NULL) < 0) {
                log_error("Failed to set up timerfd: %m");
                return -errno;
        }

        e = sd_event_source_get_event(sntp->event_receive);
        r = sd_event_add_io(e, &source, fd, EPOLLIN, sntp_clock_watch, sntp);
        if (r < 0) {
                log_error("Failed to create clock watch event source: %s", strerror(-r));
                return r;
        }

        sd_event_source_unref(sntp->event_clock_watch);
        sntp->event_clock_watch = source;

        if (sntp->clock_watch_fd >= 0)
                close(sntp->clock_watch_fd);
        sntp->clock_watch_fd = fd;
        fd = -1;

        return 0;
}

static int sntp_adjust_clock(SNTPContext *sntp, double offset, int leap_sec) {
        struct timex tmx = {};
        int r;

        /*
         * For small deltas, tell the kernel to gradually adjust the system
         * clock to the NTP time, larger deltas are just directly set.
         *
         * Clear STA_UNSYNC, it will enable the kernel's 11-minute mode, which
         * syncs the system time periodically to the hardware clock.
         */
        if (offset < NTP_MAX_ADJUST && offset > -NTP_MAX_ADJUST) {
                tmx.modes |= ADJ_STATUS | ADJ_OFFSET | ADJ_TIMECONST | ADJ_MAXERROR | ADJ_ESTERROR;
                tmx.status = STA_PLL;
                tmx.offset = offset * 1000 * 1000;
                tmx.constant = log2i(sntp->poll_interval_usec / USEC_PER_SEC) - 6;
                tmx.maxerror = 0;
                tmx.esterror = 0;
                log_debug("  adjust (slew): %+f sec\n", (double)tmx.offset / USEC_PER_SEC);
        } else {
                tmx.modes = ADJ_SETOFFSET;
                d_to_tv(offset, &tmx.time);

                sntp->jumped = true;
                log_debug("  adjust (jump): %+f sec\n", tv_to_d(&tmx.time));
        }

        switch (leap_sec) {
        case 1:
                tmx.status |= STA_INS;
                break;
        case -1:
                tmx.status |= STA_DEL;
                break;
        }

        r = clock_adjtime(CLOCK_REALTIME, &tmx);
        if (r < 0)
                return r;

        log_debug("  status       : %04i %s\n"
                  "  time now     : %li.%06li\n"
                  "  constant     : %li\n"
                  "  offset       : %+f sec\n"
                  "  freq offset  : %+li (%+.3f ppm)\n",
                  tmx.status, tmx.status & STA_UNSYNC ? "" : "sync",
                  tmx.time.tv_sec, tmx.time.tv_usec,
                  tmx.constant,
                  (double)tmx.offset / USEC_PER_SEC,
                  tmx.freq, (double)tmx.freq / 65536);

        return 0;
}

static bool sntp_sample_spike_detection(SNTPContext *sntp, double offset, double delay) {
        unsigned int i, idx_cur, idx_new, idx_min;
        double jitter;
        double j;

        /* store the current data in our samples array */
        idx_cur = sntp->samples_idx;
        idx_new = (idx_cur + 1) % ELEMENTSOF(sntp->samples);
        sntp->samples_idx = idx_new;
        sntp->samples[idx_new].offset = offset;
        sntp->samples[idx_new].delay = delay;

        sntp->packet_count++;
        jitter = sntp->samples_jitter;

        /* calculate new jitter value from the RMS differences relative to the lowest delay sample */
        for (idx_min = idx_cur, i = 0; i < ELEMENTSOF(sntp->samples); i++)
                if (sntp->samples[i].delay > 0 && sntp->samples[i].delay < sntp->samples[idx_min].delay)
                        idx_min = i;

        j = 0;
        for (i = 0; i < ELEMENTSOF(sntp->samples); i++)
                j += square(sntp->samples[i].offset - sntp->samples[idx_min].offset);
        sntp->samples_jitter = sqrt(j / (ELEMENTSOF(sntp->samples) - 1));

        /* ignore samples when resyncing */
        if (sntp->poll_resync)
                return false;

        /* always accept offset if we are farther off than the round-trip delay */
        if (fabs(offset) > delay)
                return false;

        /* we need a few samples before looking at them */
        if (sntp->packet_count < 4)
                return false;

        /* do not accept anything worse than the maximum possible error of the best sample */
        if (fabs(offset) > sntp->samples[idx_min].delay)
                return true;

        /* compare the difference between the current offset to the previous offset and jitter */
        return fabs(offset - sntp->samples[idx_cur].offset) > 3 * jitter;
}
Ejemplo n.º 10
0
static int interrupt_signal_handler(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) {
        log_notice("Transfer aborted.");
        sd_event_exit(sd_event_source_get_event(s), EINTR);
        return 0;
}