mirror of
https://github.com/systemd/systemd-stable.git
synced 2024-12-24 21:34:08 +03:00
logind: use sd_event timer source for inhibitor logic
Instead of open-coding the delayed action and inhibit timeout logic, switch over to a real sd_event_source based implementation. This is not only easier to read but also allows us to add more timers in the future.
This commit is contained in:
parent
3f61a7a6eb
commit
c0f3280508
@ -1459,17 +1459,75 @@ static int execute_shutdown_or_sleep(
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int manager_inhibit_timeout_handler(
|
||||||
|
sd_event_source *s,
|
||||||
|
uint64_t usec,
|
||||||
|
void *userdata) {
|
||||||
|
|
||||||
|
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
|
||||||
|
Inhibitor *offending = NULL;
|
||||||
|
Manager *manager = userdata;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
assert(manager);
|
||||||
|
assert(manager->inhibit_timeout_source == s);
|
||||||
|
|
||||||
|
if (manager->action_what == 0 || manager->action_job)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (manager_is_inhibited(manager, manager->action_what, INHIBIT_DELAY, NULL, false, false, 0, &offending)) {
|
||||||
|
_cleanup_free_ char *comm = NULL, *u = NULL;
|
||||||
|
|
||||||
|
(void) get_process_comm(offending->pid, &comm);
|
||||||
|
u = uid_to_name(offending->uid);
|
||||||
|
|
||||||
|
log_notice("Delay lock is active (UID "UID_FMT"/%s, PID "PID_FMT"/%s) but inhibitor timeout is reached.",
|
||||||
|
offending->uid, strna(u),
|
||||||
|
offending->pid, strna(comm));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Actually do the operation */
|
||||||
|
r = execute_shutdown_or_sleep(manager, manager->action_what, manager->action_unit, &error);
|
||||||
|
if (r < 0) {
|
||||||
|
log_warning("Failed to send delayed message: %s", bus_error_message(&error, r));
|
||||||
|
|
||||||
|
manager->action_unit = NULL;
|
||||||
|
manager->action_what = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int delay_shutdown_or_sleep(
|
static int delay_shutdown_or_sleep(
|
||||||
Manager *m,
|
Manager *m,
|
||||||
InhibitWhat w,
|
InhibitWhat w,
|
||||||
const char *unit_name) {
|
const char *unit_name) {
|
||||||
|
|
||||||
|
int r;
|
||||||
|
usec_t timeout_val;
|
||||||
|
|
||||||
assert(m);
|
assert(m);
|
||||||
assert(w >= 0);
|
assert(w >= 0);
|
||||||
assert(w < _INHIBIT_WHAT_MAX);
|
assert(w < _INHIBIT_WHAT_MAX);
|
||||||
assert(unit_name);
|
assert(unit_name);
|
||||||
|
|
||||||
m->action_timestamp = now(CLOCK_MONOTONIC);
|
timeout_val = now(CLOCK_MONOTONIC) + m->inhibit_delay_max;
|
||||||
|
|
||||||
|
if (m->inhibit_timeout_source) {
|
||||||
|
r = sd_event_source_set_time(m->inhibit_timeout_source, timeout_val);
|
||||||
|
if (r < 0)
|
||||||
|
return log_error_errno(r, "sd_event_source_set_time() failed: %m\n");
|
||||||
|
|
||||||
|
r = sd_event_source_set_enabled(m->inhibit_timeout_source, SD_EVENT_ONESHOT);
|
||||||
|
if (r < 0)
|
||||||
|
return log_error_errno(r, "sd_event_source_set_enabled() failed: %m\n");
|
||||||
|
} else {
|
||||||
|
r = sd_event_add_time(m->event, &m->inhibit_timeout_source, CLOCK_MONOTONIC,
|
||||||
|
timeout_val, 0, manager_inhibit_timeout_handler, m);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
m->action_unit = unit_name;
|
m->action_unit = unit_name;
|
||||||
m->action_what = w;
|
m->action_what = w;
|
||||||
|
|
||||||
@ -2358,44 +2416,6 @@ int manager_send_changed(Manager *manager, const char *property, ...) {
|
|||||||
l);
|
l);
|
||||||
}
|
}
|
||||||
|
|
||||||
int manager_dispatch_delayed(Manager *manager) {
|
|
||||||
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
|
|
||||||
Inhibitor *offending = NULL;
|
|
||||||
int r;
|
|
||||||
|
|
||||||
assert(manager);
|
|
||||||
|
|
||||||
if (manager->action_what == 0 || manager->action_job)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
/* Continue delay? */
|
|
||||||
if (manager_is_inhibited(manager, manager->action_what, INHIBIT_DELAY, NULL, false, false, 0, &offending)) {
|
|
||||||
_cleanup_free_ char *comm = NULL, *u = NULL;
|
|
||||||
|
|
||||||
get_process_comm(offending->pid, &comm);
|
|
||||||
u = uid_to_name(offending->uid);
|
|
||||||
|
|
||||||
if (manager->action_timestamp + manager->inhibit_delay_max > now(CLOCK_MONOTONIC))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
log_info("Delay lock is active (UID "UID_FMT"/%s, PID "PID_FMT"/%s) but inhibitor timeout is reached.",
|
|
||||||
offending->uid, strna(u),
|
|
||||||
offending->pid, strna(comm));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Actually do the operation */
|
|
||||||
r = execute_shutdown_or_sleep(manager, manager->action_what, manager->action_unit, &error);
|
|
||||||
if (r < 0) {
|
|
||||||
log_warning("Failed to send delayed message: %s", bus_error_message(&error, r));
|
|
||||||
|
|
||||||
manager->action_unit = NULL;
|
|
||||||
manager->action_what = 0;
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int manager_start_scope(
|
int manager_start_scope(
|
||||||
Manager *manager,
|
Manager *manager,
|
||||||
const char *scope,
|
const char *scope,
|
||||||
|
@ -141,6 +141,7 @@ void manager_free(Manager *m) {
|
|||||||
set_free_free(m->busnames);
|
set_free_free(m->busnames);
|
||||||
|
|
||||||
sd_event_source_unref(m->idle_action_event_source);
|
sd_event_source_unref(m->idle_action_event_source);
|
||||||
|
sd_event_source_unref(m->inhibit_timeout_source);
|
||||||
|
|
||||||
sd_event_source_unref(m->console_active_event_source);
|
sd_event_source_unref(m->console_active_event_source);
|
||||||
sd_event_source_unref(m->udev_seat_event_source);
|
sd_event_source_unref(m->udev_seat_event_source);
|
||||||
@ -1093,8 +1094,6 @@ int manager_run(Manager *m) {
|
|||||||
assert(m);
|
assert(m);
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
usec_t us = (uint64_t) -1;
|
|
||||||
|
|
||||||
r = sd_event_get_state(m->event);
|
r = sd_event_get_state(m->event);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
@ -1103,19 +1102,7 @@ int manager_run(Manager *m) {
|
|||||||
|
|
||||||
manager_gc(m, true);
|
manager_gc(m, true);
|
||||||
|
|
||||||
if (manager_dispatch_delayed(m) > 0)
|
r = sd_event_run(m->event, (uint64_t) -1);
|
||||||
continue;
|
|
||||||
|
|
||||||
if (m->action_what != 0 && !m->action_job) {
|
|
||||||
usec_t x, y;
|
|
||||||
|
|
||||||
x = now(CLOCK_MONOTONIC);
|
|
||||||
y = m->action_timestamp + m->inhibit_delay_max;
|
|
||||||
|
|
||||||
us = x >= y ? 0 : y - x;
|
|
||||||
}
|
|
||||||
|
|
||||||
r = sd_event_run(m->event, us);
|
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
@ -95,7 +95,7 @@ struct Manager {
|
|||||||
/* If a shutdown/suspend is currently executed, then this is
|
/* If a shutdown/suspend is currently executed, then this is
|
||||||
* the job of it */
|
* the job of it */
|
||||||
char *action_job;
|
char *action_job;
|
||||||
usec_t action_timestamp;
|
sd_event_source *inhibit_timeout_source;
|
||||||
|
|
||||||
sd_event_source *idle_action_event_source;
|
sd_event_source *idle_action_event_source;
|
||||||
usec_t idle_action_usec;
|
usec_t idle_action_usec;
|
||||||
@ -167,8 +167,6 @@ int bus_manager_shutdown_or_sleep_now_or_later(Manager *m, const char *unit_name
|
|||||||
|
|
||||||
int manager_send_changed(Manager *manager, const char *property, ...) _sentinel_;
|
int manager_send_changed(Manager *manager, const char *property, ...) _sentinel_;
|
||||||
|
|
||||||
int manager_dispatch_delayed(Manager *manager);
|
|
||||||
|
|
||||||
int manager_start_scope(Manager *manager, const char *scope, pid_t pid, const char *slice, const char *description, const char *after, const char *after2, sd_bus_error *error, char **job);
|
int manager_start_scope(Manager *manager, const char *scope, pid_t pid, const char *slice, const char *description, const char *after, const char *after2, sd_bus_error *error, char **job);
|
||||||
int manager_start_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job);
|
int manager_start_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job);
|
||||||
int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job);
|
int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job);
|
||||||
|
Loading…
Reference in New Issue
Block a user