From 99b43caf26787ac9376e10c14f6a5bcf056f900c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Kl=C3=B6tzke?= Date: Wed, 7 Mar 2018 14:16:49 +0100 Subject: [PATCH] core: immediately trigger watchdog action on WATCHDOG=trigger A service might be able to detect errors by itself that may require the system to take the same action as if the service locked up. Add a WATCHDOG=trigger state change notification to sd_notify() to let the service manager know about the self-detected misery and instantly trigger the configured watchdog behaviour. --- man/sd_notify.xml | 12 ++++++++++++ src/core/service.c | 21 +++++++++++++++++++-- 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/man/sd_notify.xml b/man/sd_notify.xml index 0084bf38829..00640cb290d 100644 --- a/man/sd_notify.xml +++ b/man/sd_notify.xml @@ -173,6 +173,18 @@ watchdog is enabled. + + WATCHDOG=trigger + + Tells the service manager that the service detected an internal error that should be handled by + the configured watchdog options. This will trigger the same behaviour as if WatchdogSec= is + enabled and the service did not send WATCHDOG=1 in time. Note that + WatchdogSec= does not need to be enabled for WATCHDOG=trigger to trigger + the watchdog action. See + systemd.service5 for + information about the watchdog behavior. + + WATCHDOG_USEC=… diff --git a/src/core/service.c b/src/core/service.c index c4d83785578..56667f03e85 100644 --- a/src/core/service.c +++ b/src/core/service.c @@ -3742,6 +3742,16 @@ static bool service_notify_message_authorized(Service *s, pid_t pid, char **tags return true; } +static void service_force_watchdog(Service *s) { + if (!UNIT(s)->manager->service_watchdogs) + return; + + log_unit_error(UNIT(s), "Watchdog request (last status: %s)!", + s->status_text ? s->status_text : ""); + + service_enter_signal(s, SERVICE_STOP_WATCHDOG, SERVICE_FAILURE_WATCHDOG); +} + static void service_notify_message( Unit *u, const struct ucred *ucred, @@ -3888,8 +3898,15 @@ static void service_notify_message( } /* Interpret WATCHDOG= */ - if (strv_find(tags, "WATCHDOG=1")) - service_reset_watchdog(s); + e = strv_find_startswith(tags, "WATCHDOG="); + if (e) { + if (streq(e, "1")) + service_reset_watchdog(s); + else if (streq(e, "trigger")) + service_force_watchdog(s); + else + log_unit_warning(u, "Passed WATCHDOG= field is invalid, ignoring."); + } e = strv_find_startswith(tags, "WATCHDOG_USEC="); if (e) {