1
1
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:
Daniel Mack 2015-04-11 18:44:51 +02:00
parent 3f61a7a6eb
commit c0f3280508
3 changed files with 62 additions and 57 deletions

View File

@ -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,

View File

@ -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;
} }

View File

@ -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);