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(), ¤t) >= 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; }
int link_lldp_emit_start(Link *link) { usec_t next; int r; assert(link); if (!link->network || link->network->lldp_emit == LLDP_EMIT_NO) { link_lldp_emit_stop(link); return 0; } /* Starts the LLDP transmission in "fast" mode. If it is already started, turns "fast" mode back on again. */ link->lldp_tx_fast = LLDP_TX_FAST_INIT; next = usec_add(usec_add(now(clock_boottime_or_monotonic()), LLDP_FAST_TX_USEC), (usec_t) random_u64() % LLDP_JITTER_USEC); if (link->lldp_emit_event_source) { usec_t old; /* Lower the timeout, maybe */ r = sd_event_source_get_time(link->lldp_emit_event_source, &old); if (r < 0) return r; if (old <= next) return 0; return sd_event_source_set_time(link->lldp_emit_event_source, next); } else { r = sd_event_add_time( link->manager->event, &link->lldp_emit_event_source, clock_boottime_or_monotonic(), next, 0, on_lldp_timer, link); if (r < 0) return r; (void) sd_event_source_set_description(link->lldp_emit_event_source, "lldp-tx"); } return 0; }
static void test_usec_add(void) { log_info("/* %s */", __func__); assert_se(usec_add(0, 0) == 0); assert_se(usec_add(1, 4) == 5); assert_se(usec_add(USEC_INFINITY, 5) == USEC_INFINITY); assert_se(usec_add(5, USEC_INFINITY) == USEC_INFINITY); assert_se(usec_add(USEC_INFINITY-5, 2) == USEC_INFINITY-3); assert_se(usec_add(USEC_INFINITY-2, 2) == USEC_INFINITY); assert_se(usec_add(USEC_INFINITY-1, 2) == USEC_INFINITY); assert_se(usec_add(USEC_INFINITY, 2) == USEC_INFINITY); }
static void scope_enter_signal(Scope *s, ScopeState state, ScopeResult f) { bool skip_signal = false; int r; assert(s); if (s->result == SCOPE_SUCCESS) s->result = f; /* Before sending any signal, make sure we track all members of this cgroup */ (void) unit_watch_all_pids(UNIT(s)); /* Also, enqueue a job that we recheck all our PIDs a bit later, given that it's likely some processes have * died now */ (void) unit_enqueue_rewatch_pids(UNIT(s)); /* If we have a controller set let's ask the controller nicely to terminate the scope, instead of us going * directly into SIGTERM berserk mode */ if (state == SCOPE_STOP_SIGTERM) skip_signal = bus_scope_send_request_stop(s) > 0; if (skip_signal) r = 1; /* wait */ else { r = unit_kill_context( UNIT(s), &s->kill_context, state != SCOPE_STOP_SIGTERM ? KILL_KILL : s->was_abandoned ? KILL_TERMINATE_AND_LOG : KILL_TERMINATE, -1, -1, false); if (r < 0) goto fail; } if (r > 0) { r = scope_arm_timer(s, usec_add(now(CLOCK_MONOTONIC), s->timeout_stop_usec)); if (r < 0) goto fail; scope_set_state(s, state); } else if (state == SCOPE_STOP_SIGTERM) scope_enter_signal(s, SCOPE_STOP_SIGKILL, SCOPE_SUCCESS); else scope_enter_dead(s, SCOPE_SUCCESS); return; fail: log_unit_warning_errno(UNIT(s), r, "Failed to kill processes: %m"); scope_enter_dead(s, SCOPE_FAILURE_RESOURCES); }
static void scope_enter_signal(Scope *s, ScopeState state, ScopeResult f) { bool skip_signal = false; int r; assert(s); if (s->result == SCOPE_SUCCESS) s->result = f; unit_watch_all_pids(UNIT(s)); /* If we have a controller set let's ask the controller nicely * to terminate the scope, instead of us going directly into * SIGTERM berserk mode */ if (state == SCOPE_STOP_SIGTERM) skip_signal = bus_scope_send_request_stop(s) > 0; if (skip_signal) r = 1; /* wait */ else { r = unit_kill_context( UNIT(s), &s->kill_context, state != SCOPE_STOP_SIGTERM ? KILL_KILL : s->was_abandoned ? KILL_TERMINATE_AND_LOG : KILL_TERMINATE, -1, -1, false); if (r < 0) goto fail; } if (r > 0) { r = scope_arm_timer(s, usec_add(now(CLOCK_MONOTONIC), s->timeout_stop_usec)); if (r < 0) goto fail; scope_set_state(s, state); } else if (state == SCOPE_STOP_SIGTERM) scope_enter_signal(s, SCOPE_STOP_SIGKILL, SCOPE_SUCCESS); else scope_enter_dead(s, SCOPE_SUCCESS); return; fail: log_unit_warning_errno(UNIT(s), r, "Failed to kill processes: %m"); scope_enter_dead(s, SCOPE_FAILURE_RESOURCES); }
static int busname_make_starter(BusName *n, pid_t *_pid) { pid_t pid; int r; r = busname_arm_timer(n, usec_add(now(CLOCK_MONOTONIC), n->timeout_usec)); if (r < 0) goto fail; /* We have to resolve the user/group names out-of-process, * hence let's fork here. It's messy, but well, what can we * do? */ pid = fork(); if (pid < 0) return -errno; if (pid == 0) { int ret; (void) default_signals(SIGNALS_CRASH_HANDLER, SIGNALS_IGNORE, -1); (void) ignore_signals(SIGPIPE, -1); log_forget_fds(); r = bus_kernel_make_starter(n->starter_fd, n->name, n->activating, n->accept_fd, n->policy, n->policy_world); if (r < 0) { ret = EXIT_MAKE_STARTER; goto fail_child; } _exit(0); fail_child: log_open(); log_error_errno(r, "Failed to create starter connection at step %s: %m", exit_status_to_string(ret, EXIT_STATUS_SYSTEMD)); _exit(ret); } r = unit_watch_pid(UNIT(n), pid); if (r < 0) goto fail; *_pid = pid; return 0; fail: n->timer_event_source = sd_event_source_unref(n->timer_event_source); return r; }
static void busname_enter_signal(BusName *n, BusNameState state, BusNameResult f) { KillContext kill_context = {}; int r; assert(n); if (n->result == BUSNAME_SUCCESS) n->result = f; kill_context_init(&kill_context); r = unit_kill_context(UNIT(n), &kill_context, state != BUSNAME_SIGTERM ? KILL_KILL : KILL_TERMINATE, -1, n->control_pid, false); if (r < 0) { log_unit_warning_errno(UNIT(n), r, "Failed to kill control process: %m"); goto fail; } if (r > 0) { r = busname_arm_timer(n, usec_add(now(CLOCK_MONOTONIC), n->timeout_usec)); if (r < 0) { log_unit_warning_errno(UNIT(n), r, "Failed to arm timer: %m"); goto fail; } busname_set_state(n, state); } else if (state == BUSNAME_SIGTERM) busname_enter_signal(n, BUSNAME_SIGKILL, BUSNAME_SUCCESS); else busname_enter_dead(n, BUSNAME_SUCCESS); return; fail: busname_enter_dead(n, BUSNAME_FAILURE_RESOURCES); }
static int scope_coldplug(Unit *u) { Scope *s = SCOPE(u); int r; assert(s); assert(s->state == SCOPE_DEAD); if (s->deserialized_state == s->state) return 0; if (IN_SET(s->deserialized_state, SCOPE_STOP_SIGKILL, SCOPE_STOP_SIGTERM)) { r = scope_arm_timer(s, usec_add(u->state_change_timestamp.monotonic, s->timeout_stop_usec)); if (r < 0) return r; } if (!IN_SET(s->deserialized_state, SCOPE_DEAD, SCOPE_FAILED)) unit_watch_all_pids(UNIT(s)); scope_set_state(s, s->deserialized_state); return 0; }
static int busname_coldplug(Unit *u) { BusName *n = BUSNAME(u); int r; assert(n); assert(n->state == BUSNAME_DEAD); if (n->deserialized_state == n->state) return 0; if (n->control_pid > 0 && pid_is_unwaited(n->control_pid) && IN_SET(n->deserialized_state, BUSNAME_MAKING, BUSNAME_SIGTERM, BUSNAME_SIGKILL)) { r = unit_watch_pid(UNIT(n), n->control_pid); if (r < 0) return r; r = busname_arm_timer(n, usec_add(u->state_change_timestamp.monotonic, n->timeout_usec)); if (r < 0) return r; } if (IN_SET(n->deserialized_state, BUSNAME_MAKING, BUSNAME_LISTENING, BUSNAME_REGISTERED, BUSNAME_RUNNING)) { r = busname_open_fd(n); if (r < 0) return r; } if (n->deserialized_state == BUSNAME_LISTENING) { r = busname_watch_fd(n); if (r < 0) return r; } busname_set_state(n, n->deserialized_state); return 0; }