]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
core: immediately trigger watchdog action on WATCHDOG=trigger
authorJan Klötzke <Jan.Kloetzke@preh.de>
Wed, 7 Mar 2018 13:16:49 +0000 (14:16 +0100)
committerLennart Poettering <lennart@poettering.net>
Wed, 24 Apr 2019 08:17:10 +0000 (10:17 +0200)
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
src/core/service.c

index 0084bf388298a342a93dc9c0027c286d000c35b3..00640cb290d1f0bf6c42d9c8a727e255f45986c7 100644 (file)
         watchdog is enabled. </para></listitem>
       </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>
 
index c4d837855785fc8737574e9a251e796d8ad37eda..56667f03e851c4e0649e662789860fff48ad391a 100644 (file)
@@ -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) {