summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Klötzke <Jan.Kloetzke@preh.de>2018-03-07 14:16:49 +0100
committerLennart Poettering <lennart@poettering.net>2019-04-24 10:17:10 +0200
commit99b43caf26787ac9376e10c14f6a5bcf056f900c (patch)
treef6a5b5fa7f87664876e23bbda4641b3458765f68
parent1329fee5da676a0d489416aade59060469a46c43 (diff)
downloadsystemd-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.xml12
-rw-r--r--src/core/service.c21
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) {