pid1: add option to disable service watchdogs
authorJan Klötzke <Jan.Kloetzke@preh.de>
Mon, 20 Mar 2017 12:10:43 +0000 (13:10 +0100)
committerJan Klötzke <jan@kloetzke.net>
Mon, 22 Jan 2018 17:10:03 +0000 (18:10 +0100)
Add a "systemd.service_watchdogs=" option to the command line which
disables all service runtime watchdogs and emergency actions.

man/kernel-command-line.xml
man/systemd.xml
src/core/dbus-manager.c
src/core/emergency-action.c
src/core/main.c
src/core/manager.c
src/core/manager.h
src/core/service.c

index 422c060..be55f14 100644 (file)
@@ -85,6 +85,7 @@
         <term><varname>systemd.crash_shell</varname></term>
         <term><varname>systemd.crash_reboot</varname></term>
         <term><varname>systemd.confirm_spawn</varname></term>
+        <term><varname>systemd.service_watchdogs</varname></term>
         <term><varname>systemd.show_status</varname></term>
         <term><varname>systemd.log_target=</varname></term>
         <term><varname>systemd.log_level=</varname></term>
index 1c644d1..ad2c1e4 100644 (file)
         to all zeros.</para></listitem>
       </varlistentry>
 
+      <varlistentry>
+        <term><option>--service-watchdogs=</option></term>
+
+        <listitem><para>Globally enable/disable all service watchdog timeouts and emergency
+        actions. This setting may also be specified during boot, on the kernel
+        command line via the <varname>systemd.service_watchdogs=</varname>
+        option, see below. Defaults to enabled.</para></listitem>
+      </varlistentry>
+
       <xi:include href="standard-options.xml" xpointer="help" />
       <xi:include href="standard-options.xml" xpointer="version" />
     </variablelist>
       </varlistentry>
 
       <varlistentry>
+        <term><varname>systemd.service_watchdogs=</varname></term>
+
+        <listitem><para>Takes a boolean argument. If disabled, all service runtime
+        watchdogs (<option>WatchdogSec=</option>) and emergency actions (e.g.
+        <option>OnFailure=</option> or <option>StartLimitAction=</option>) are
+        ignored by the system manager (PID 1); see
+        <citerefentry><refentrytitle>systemd.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
+        Defaults to enabled, i.e. watchdogs and failure actions are processed
+        normally. The hardware watchdog is not affected by this
+        option.</para></listitem>
+      </varlistentry>
+
+      <varlistentry>
         <term><varname>systemd.show_status</varname></term>
 
         <listitem><para>Takes a boolean argument or the constant
index 721cad4..4fe3748 100644 (file)
@@ -2416,6 +2416,7 @@ const sd_bus_vtable bus_manager_vtable[] = {
         SD_BUS_PROPERTY("DefaultStandardError", "s", bus_property_get_exec_output, offsetof(Manager, default_std_output), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_WRITABLE_PROPERTY("RuntimeWatchdogUSec", "t", bus_property_get_usec, property_set_runtime_watchdog, offsetof(Manager, runtime_watchdog), 0),
         SD_BUS_WRITABLE_PROPERTY("ShutdownWatchdogUSec", "t", bus_property_get_usec, bus_property_set_usec, offsetof(Manager, shutdown_watchdog), 0),
+        SD_BUS_WRITABLE_PROPERTY("ServiceWatchdogs", "b", bus_property_get_bool, bus_property_set_bool, offsetof(Manager, service_watchdogs), 0),
         SD_BUS_PROPERTY("ControlGroup", "s", NULL, offsetof(Manager, cgroup_root), 0),
         SD_BUS_PROPERTY("SystemState", "s", property_get_system_state, 0, 0),
         SD_BUS_PROPERTY("ExitCode", "y", bus_property_get_unsigned, offsetof(Manager, return_value), 0),
index 308608e..decfacd 100644 (file)
@@ -49,6 +49,11 @@ int emergency_action(
         if (action == EMERGENCY_ACTION_NONE)
                 return -ECANCELED;
 
+        if (!m->service_watchdogs) {
+                log_warning("Watchdog disabled! Not acting on: %s", reason);
+                return -ECANCELED;
+        }
+
         if (!MANAGER_IS_SYSTEM(m)) {
                 /* Downgrade all options to simply exiting if we run
                  * in user mode */
index a088913..7d20f4e 100644 (file)
@@ -112,6 +112,7 @@ static char *arg_confirm_spawn = NULL;
 static ShowStatus arg_show_status = _SHOW_STATUS_UNSET;
 static bool arg_switched_root = false;
 static bool arg_no_pager = false;
+static bool arg_service_watchdogs = true;
 static char ***arg_join_controllers = NULL;
 static ExecOutput arg_default_std_output = EXEC_OUTPUT_JOURNAL;
 static ExecOutput arg_default_std_error = EXEC_OUTPUT_INHERIT;
@@ -396,6 +397,14 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
                         arg_confirm_spawn = s;
                 }
 
+        } else if (proc_cmdline_key_streq(key, "systemd.service_watchdogs")) {
+
+                r = value ? parse_boolean(value) : true;
+                if (r < 0)
+                        log_warning("Failed to parse service watchdog switch %s. Ignoring.", value);
+                else
+                        arg_service_watchdogs = r;
+
         } else if (proc_cmdline_key_streq(key, "systemd.show_status")) {
 
                 if (value) {
@@ -855,6 +864,7 @@ static void set_manager_settings(Manager *m) {
         assert(m);
 
         m->confirm_spawn = arg_confirm_spawn;
+        m->service_watchdogs = arg_service_watchdogs;
         m->runtime_watchdog = arg_runtime_watchdog;
         m->shutdown_watchdog = arg_shutdown_watchdog;
         m->cad_burst_action = arg_cad_burst_action;
@@ -886,7 +896,8 @@ static int parse_argv(int argc, char *argv[]) {
                 ARG_SWITCHED_ROOT,
                 ARG_DEFAULT_STD_OUTPUT,
                 ARG_DEFAULT_STD_ERROR,
-                ARG_MACHINE_ID
+                ARG_MACHINE_ID,
+                ARG_SERVICE_WATCHDOGS,
         };
 
         static const struct option options[] = {
@@ -913,6 +924,7 @@ static int parse_argv(int argc, char *argv[]) {
                 { "default-standard-output",  required_argument, NULL, ARG_DEFAULT_STD_OUTPUT,      },
                 { "default-standard-error",   required_argument, NULL, ARG_DEFAULT_STD_ERROR,       },
                 { "machine-id",               required_argument, NULL, ARG_MACHINE_ID               },
+                { "service-watchdogs",        required_argument, NULL, ARG_SERVICE_WATCHDOGS        },
                 {}
         };
 
@@ -1067,6 +1079,13 @@ static int parse_argv(int argc, char *argv[]) {
                                 return log_error_errno(r, "Failed to parse confirm spawn option: %m");
                         break;
 
+                case ARG_SERVICE_WATCHDOGS:
+                        r = parse_boolean(optarg);
+                        if (r < 0)
+                                return log_error_errno(r, "Failed to parse service watchdogs boolean: %s", optarg);
+                        arg_service_watchdogs = r;
+                        break;
+
                 case ARG_SHOW_STATUS:
                         if (optarg) {
                                 r = parse_show_status(optarg, &arg_show_status);
index ee9ff15..a6037c3 100644 (file)
@@ -2659,6 +2659,7 @@ int manager_serialize(Manager *m, FILE *f, FDSet *fds, bool switching_root) {
         fprintf(f, "taint-usr=%s\n", yes_no(m->taint_usr));
         fprintf(f, "ready-sent=%s\n", yes_no(m->ready_sent));
         fprintf(f, "taint-logged=%s\n", yes_no(m->taint_logged));
+        fprintf(f, "service-watchdogs=%s\n", yes_no(m->service_watchdogs));
 
         for (q = 0; q < _MANAGER_TIMESTAMP_MAX; q++) {
                 /* The userspace and finish timestamps only apply to the host system, hence only serialize them there */
@@ -2830,6 +2831,15 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) {
                         else
                                 m->taint_logged = m->taint_logged || b;
 
+                } else if ((val = startswith(l, "service-watchdogs="))) {
+                        int b;
+
+                        b = parse_boolean(val);
+                        if (b < 0)
+                                log_notice("Failed to parse service-watchdogs flag %s", val);
+                        else
+                                m->service_watchdogs = b;
+
                 } else if (startswith(l, "env=")) {
                         r = deserialize_environment(&m->environment, l);
                         if (r == -ENOMEM)
index 1531374..b01edea 100644 (file)
@@ -277,6 +277,7 @@ struct Manager {
         ShowStatus show_status;
         char *confirm_spawn;
         bool no_console_output;
+        bool service_watchdogs;
 
         ExecOutput default_std_output, default_std_error;
 
index 44d9ca0..969e9b4 100644 (file)
@@ -3419,10 +3419,14 @@ static int service_dispatch_watchdog(sd_event_source *source, usec_t usec, void
 
         watchdog_usec = service_get_watchdog_usec(s);
 
-        log_unit_error(UNIT(s), "Watchdog timeout (limit %s)!",
-                       format_timespan(t, sizeof(t), watchdog_usec, 1));
+        if (UNIT(s)->manager->service_watchdogs) {
+                log_unit_error(UNIT(s), "Watchdog timeout (limit %s)!",
+                               format_timespan(t, sizeof(t), watchdog_usec, 1));
 
-        service_enter_signal(s, SERVICE_STOP_SIGABRT, SERVICE_FAILURE_WATCHDOG);
+                service_enter_signal(s, SERVICE_STOP_SIGABRT, SERVICE_FAILURE_WATCHDOG);
+        } else
+                log_unit_warning(UNIT(s), "Watchdog disabled! Ignoring watchdog timeout (limit %s)!",
+                                 format_timespan(t, sizeof(t), watchdog_usec, 1));
 
         return 0;
 }