From c0f32805086ff65d2905b0e3a9166d9ed6c2bc41 Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Sat, 11 Apr 2015 18:44:51 +0200 Subject: 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. --- src/login/logind-dbus.c | 98 +++++++++++++++++++++++++++++-------------------- src/login/logind.c | 17 +-------- src/login/logind.h | 4 +- 3 files changed, 62 insertions(+), 57 deletions(-) (limited to 'src/login') diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c index 037459be71..e8a92db691 100644 --- a/src/login/logind-dbus.c +++ b/src/login/logind-dbus.c @@ -1459,17 +1459,75 @@ static int execute_shutdown_or_sleep( 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( Manager *m, InhibitWhat w, const char *unit_name) { + int r; + usec_t timeout_val; + assert(m); assert(w >= 0); assert(w < _INHIBIT_WHAT_MAX); 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_what = w; @@ -2358,44 +2416,6 @@ int manager_send_changed(Manager *manager, const char *property, ...) { 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( Manager *manager, const char *scope, diff --git a/src/login/logind.c b/src/login/logind.c index 707d528fbb..ea7c6e74b0 100644 --- a/src/login/logind.c +++ b/src/login/logind.c @@ -141,6 +141,7 @@ void manager_free(Manager *m) { set_free_free(m->busnames); 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->udev_seat_event_source); @@ -1093,8 +1094,6 @@ int manager_run(Manager *m) { assert(m); for (;;) { - usec_t us = (uint64_t) -1; - r = sd_event_get_state(m->event); if (r < 0) return r; @@ -1103,19 +1102,7 @@ int manager_run(Manager *m) { manager_gc(m, true); - if (manager_dispatch_delayed(m) > 0) - 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); + r = sd_event_run(m->event, (uint64_t) -1); if (r < 0) return r; } diff --git a/src/login/logind.h b/src/login/logind.h index 4781688f0a..caf78f734a 100644 --- a/src/login/logind.h +++ b/src/login/logind.h @@ -95,7 +95,7 @@ struct Manager { /* If a shutdown/suspend is currently executed, then this is * the job of it */ char *action_job; - usec_t action_timestamp; + sd_event_source *inhibit_timeout_source; sd_event_source *idle_action_event_source; 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_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_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); -- cgit v1.2.3-54-g00ecf