diff options
author | Jan Klötzke <Jan.Kloetzke@preh.de> | 2018-03-07 14:16:49 +0100 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2019-04-24 10:17:10 +0200 |
commit | 99b43caf26787ac9376e10c14f6a5bcf056f900c (patch) | |
tree | f6a5b5fa7f87664876e23bbda4641b3458765f68 | |
parent | 1329fee5da676a0d489416aade59060469a46c43 (diff) | |
download | systemd-99b43caf26787ac9376e10c14f6a5bcf056f900c.tar.gz |
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.
-rw-r--r-- | man/sd_notify.xml | 12 | ||||
-rw-r--r-- | 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 0084bf3882..00640cb290 100644 --- a/man/sd_notify.xml +++ b/man/sd_notify.xml @@ -174,6 +174,18 @@ </varlistentry> <varlistentry> + <term>WATCHDOG=trigger</term> + + <listitem><para>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 <varname>WatchdogSec=</varname> is + enabled and the service did not send <literal>WATCHDOG=1</literal> in time. Note that + <varname>WatchdogSec=</varname> does not need to be enabled for <literal>WATCHDOG=trigger</literal> to trigger + the watchdog action. See + <citerefentry><refentrytitle>systemd.service</refentrytitle><manvolnum>5</manvolnum></citerefentry> for + information about the watchdog behavior. </para></listitem> + </varlistentry> + + <varlistentry> <term>WATCHDOG_USEC=…</term> <listitem><para>Reset <varname>watchdog_usec</varname> value during runtime. diff --git a/src/core/service.c b/src/core/service.c index c4d8378557..56667f03e8 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 : "<unset>"); + + 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) { |