From dc09c61f19dbf5399bf47a43b02fabd790bda37d Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 9 Oct 2024 09:42:52 +0900 Subject: [PATCH 1/4] login: allow to cancel delayed action by CancelScheduledShutdown() Fixes #34554. --- src/login/logind-dbus.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c index 6dd375c164..ee449a8445 100644 --- a/src/login/logind-dbus.c +++ b/src/login/logind-dbus.c @@ -1980,6 +1980,21 @@ static int delay_shutdown_or_sleep( return 0; } +static void cancel_delayed_action(Manager *m) { + assert(m); + + (void) sd_event_source_set_enabled(m->inhibit_timeout_source, SD_EVENT_OFF); + + /* When m->action_job is NULL, the delayed action has not been triggered yet. Let's clear it to + * accept later shutdown and friends. + * + * When m->action_job is non-NULL, the delayed action has been already triggered, and now we are + * waiting for the job being finished. In match_job_removed(), the triggered action will be used. + * Hence, do not clear it. */ + if (!m->action_job) + m->delayed_action = NULL; +} + int bus_manager_shutdown_or_sleep_now_or_later( Manager *m, const HandleActionData *a, @@ -2722,6 +2737,7 @@ static int method_cancel_scheduled_shutdown(sd_bus_message *message, void *userd username, tty, logind_wall_tty_filter, m); } + cancel_delayed_action(m); reset_scheduled_shutdown(m); return sd_bus_reply_method_return(message, "b", true); From e4b138548f33d03b7074753a84953060f9f81763 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 9 Oct 2024 10:07:31 +0900 Subject: [PATCH 2/4] login: provide delayed action in ScheduledShutdown property Even though we can get the existence of delayed action through PreparingForShutdownWithMetadata property or friends, for consistency with CancelScheduledShutdown() method, it is better to also provide the information through ScheduledShutdown property. --- src/login/logind-dbus.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c index ee449a8445..04c09ba8ab 100644 --- a/src/login/logind-dbus.c +++ b/src/login/logind-dbus.c @@ -412,10 +412,23 @@ static int property_get_scheduled_shutdown( if (r < 0) return r; - r = sd_bus_message_append( - reply, "st", - handle_action_to_string(m->scheduled_shutdown_action), - m->scheduled_shutdown_timeout); + if (m->delayed_action) { + usec_t t = m->scheduled_shutdown_timeout; /* fall back to the schedule time on failure below */ + + if (m->inhibit_timeout_source) { + r = sd_event_source_get_time(m->inhibit_timeout_source, &t); + if (r < 0) + log_debug_errno(r, "Failed to get time of inhibit timeout event source, ignoring: %m"); + } + + r = sd_bus_message_append( + reply, "st", + handle_action_to_string(m->delayed_action->handle), t); + } else + r = sd_bus_message_append( + reply, "st", + handle_action_to_string(m->scheduled_shutdown_action), + m->scheduled_shutdown_timeout); if (r < 0) return r; From 70eedbafd9621097ca54b70ac24b14e5e816d734 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 9 Oct 2024 09:22:07 +0900 Subject: [PATCH 3/4] login: use event_reset_time_relative() at one more place --- src/login/logind-dbus.c | 24 +++++++----------------- 1 file changed, 7 insertions(+), 17 deletions(-) diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c index 04c09ba8ab..b688eab0cd 100644 --- a/src/login/logind-dbus.c +++ b/src/login/logind-dbus.c @@ -1970,23 +1970,13 @@ static int delay_shutdown_or_sleep( assert(m); assert(a); - if (m->inhibit_timeout_source) { - r = sd_event_source_set_time_relative(m->inhibit_timeout_source, m->inhibit_delay_max); - if (r < 0) - return log_error_errno(r, "sd_event_source_set_time_relative() failed: %m"); - - 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"); - } else { - r = sd_event_add_time_relative( - m->event, - &m->inhibit_timeout_source, - CLOCK_MONOTONIC, m->inhibit_delay_max, 0, - manager_inhibit_timeout_handler, m); - if (r < 0) - return r; - } + r = event_reset_time_relative( + m->event, &m->inhibit_timeout_source, + CLOCK_MONOTONIC, m->inhibit_delay_max, /* accuracy = */ 0, + manager_inhibit_timeout_handler, m, + /* priority = */ 0, "inhibit-timeout", /* force = */ true); + if (r < 0) + return log_error_errno(r, "Failed to reset timer event source for inhibit timeout: %m"); m->delayed_action = a; From 0bba5435733bd5228c384d155a51dd44b9c92fb9 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Thu, 10 Oct 2024 01:50:29 +0900 Subject: [PATCH 4/4] logind: add comment why we save action in execute_shutdown_or_sleep() When I first read the code, I was confused about that. Hopefully, this helps maintain code a bit. --- src/login/logind-dbus.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c index b688eab0cd..35549e663a 100644 --- a/src/login/logind-dbus.c +++ b/src/login/logind-dbus.c @@ -1899,15 +1899,18 @@ static int execute_shutdown_or_sleep( if (r < 0) goto fail; + /* Save the action to prevent another request of shutdown or friends before the current action being + * finished. See method_do_shutdown_or_sleep(). This is also used in match_job_removed() to log what + * kind of action is finished. */ m->delayed_action = a; - /* Make sure the lid switch is ignored for a while */ + /* Make sure the lid switch is ignored for a while. */ manager_set_lid_switch_ignore(m, usec_add(now(CLOCK_MONOTONIC), m->holdoff_timeout_usec)); return 0; fail: - /* Tell people that they now may take a lock again */ + /* Tell people that they now may take a lock again. */ (void) send_prepare_for(m, a, false); return r;