[systemd-devel] [PATCH 2/4] WIP: service: add watchdog restart/reboot timeouts

Michael Olbrich m.olbrich at pengutronix.de
Wed Sep 28 09:59:16 PDT 2011


---
 src/dbus-service.c               |    4 ++++
 src/load-fragment-gperf.gperf.m4 |    2 ++
 src/service.c                    |   27 +++++++++++++++++++++++++++
 src/service.h                    |    4 ++++
 4 files changed, 37 insertions(+), 0 deletions(-)

diff --git a/src/dbus-service.c b/src/dbus-service.c
index 5a740de..34eabdf 100644
--- a/src/dbus-service.c
+++ b/src/dbus-service.c
@@ -43,6 +43,8 @@
         "  <property name=\"NotifyAccess\" type=\"s\" access=\"read\"/>\n" \
         "  <property name=\"RestartUSec\" type=\"t\" access=\"read\"/>\n" \
         "  <property name=\"TimeoutUSec\" type=\"t\" access=\"read\"/>\n" \
+        "  <property name=\"WatchdogRestartUSec\" type=\"t\" access=\"read\"/>\n" \
+        "  <property name=\"WatchdogRebootUSec\" type=\"t\" access=\"read\"/>\n" \
         "  <property name=\"WatchdogTimestamp\" type=\"t\" access=\"read\"/>\n" \
         "  <property name=\"WatchdogTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
         BUS_EXEC_COMMAND_INTERFACE("ExecStartPre")                      \
@@ -106,6 +108,8 @@ DBusHandlerResult bus_service_message_handler(Unit *u, DBusConnection *connectio
                 { "org.freedesktop.systemd1.Service", "NotifyAccess",           bus_service_append_notify_access, "s", &u->service.notify_access       },
                 { "org.freedesktop.systemd1.Service", "RestartUSec",            bus_property_append_usec,   "t", &u->service.restart_usec              },
                 { "org.freedesktop.systemd1.Service", "TimeoutUSec",            bus_property_append_usec,   "t", &u->service.timeout_usec              },
+                { "org.freedesktop.systemd1.Service", "WatchdogRestartUSec",    bus_property_append_usec,   "t", &u->service.watchdog_restart_usec     },
+                { "org.freedesktop.systemd1.Service", "WatchdogRebootUSec",     bus_property_append_usec,   "t", &u->service.watchdog_reboot_usec      },
                 { "org.freedesktop.systemd1.Service", "WatchdogTimestamp",      bus_property_append_usec,   "t", &u->service.watchdog_timestamp.realtime },
                 { "org.freedesktop.systemd1.Service", "WatchdogTimestampMonotonic",bus_property_append_usec,"t", &u->service.watchdog_timestamp.monotonic },
                 BUS_EXEC_COMMAND_PROPERTY("org.freedesktop.systemd1.Service", u->service.exec_command[SERVICE_EXEC_START_PRE],  "ExecStartPre"),
diff --git a/src/load-fragment-gperf.gperf.m4 b/src/load-fragment-gperf.gperf.m4
index 7749b88..fd5e586 100644
--- a/src/load-fragment-gperf.gperf.m4
+++ b/src/load-fragment-gperf.gperf.m4
@@ -130,6 +130,8 @@ Service.ExecStop,                config_parse_exec,                  SERVICE_EXE
 Service.ExecStopPost,            config_parse_exec,                  SERVICE_EXEC_STOP_POST,        offsetof(Service, exec_command)
 Service.RestartSec,              config_parse_usec,                  0,                             offsetof(Service, restart_usec)
 Service.TimeoutSec,              config_parse_usec,                  0,                             offsetof(Service, timeout_usec)
+Service.WatchdogRestartSec,      config_parse_usec,                  0,                             offsetof(Service, watchdog_restart_usec)
+Service.WatchdogRebootSec,       config_parse_usec,                  0,                             offsetof(Service, watchdog_reboot_usec)
 Service.Type,                    config_parse_service_type,          0,                             offsetof(Service, type)
 Service.Restart,                 config_parse_service_restart,       0,                             offsetof(Service, restart)
 Service.PermissionsStartOnly,    config_parse_bool,                  0,                             offsetof(Service, permissions_start_only)
diff --git a/src/service.c b/src/service.c
index 6fbc023..62bb0ef 100644
--- a/src/service.c
+++ b/src/service.c
@@ -112,6 +112,11 @@ static void service_init(Unit *u) {
 
         s->timeout_usec = DEFAULT_TIMEOUT_USEC;
         s->restart_usec = DEFAULT_RESTART_USEC;
+
+        s->watchdog_restart_usec = DEFAULT_TIMEOUT_USEC;
+        s->watchdog_restart_watch.type = WATCH_INVALID;
+        s->watchdog_reboot_watch.type = WATCH_INVALID;
+
         s->timer_watch.type = WATCH_INVALID;
 #ifdef HAVE_SYSV_COMPAT
         s->sysv_start_priority = -1;
@@ -197,14 +202,25 @@ static void service_connection_unref(Service *s) {
 static void service_stop_watchdog(Service *s) {
         assert(s);
 
+        unit_unwatch_timer(UNIT(s), &s->watchdog_restart_watch);
+        unit_unwatch_timer(UNIT(s), &s->watchdog_reboot_watch);
         s->watchdog_timestamp.realtime = 0;
         s->watchdog_timestamp.monotonic = 0;
 }
 
 static void service_reset_watchdog(Service *s) {
+        int r;
         assert(s);
 
         dual_timestamp_get(&s->watchdog_timestamp);
+        if (s->watchdog_restart_usec) {
+                if ((r = unit_watch_timer(UNIT(s), s->watchdog_restart_usec, &s->watchdog_restart_watch)) < 0)
+                        log_warning("%s failed to install watchdog restart timer: %s", s->meta.id, strerror(-r));
+        }
+        if (s->watchdog_restart_usec) {
+                if ((r = unit_watch_timer(UNIT(s), s->watchdog_reboot_usec, &s->watchdog_reboot_watch)) < 0)
+                        log_warning("%s failed to install watchdog reboot timer: %s", s->meta.id, strerror(-r));
+        }
 }
 
 static void service_done(Unit *u) {
@@ -2821,6 +2837,17 @@ static void service_timer_event(Unit *u, uint64_t elapsed, Watch* w) {
         assert(s);
         assert(elapsed == 1);
 
+        if (w == &s->watchdog_restart_watch) {
+                log_error("%s watchdog timeout: restarting service...", u->meta.id);
+                manager_add_job(u->meta.manager, JOB_RESTART, u, JOB_FAIL, true, 0, 0);
+                return;
+        }
+        if (w == &s->watchdog_reboot_watch) {
+                log_error("%s watchdog timeout: rebooting...", u->meta.id);
+                manager_add_job_by_name(u->meta.manager, JOB_START, "reboot.target", JOB_REPLACE, true, 0, 0);
+                return;
+        }
+
         assert(w == &s->timer_watch);
 
         switch (s->state) {
diff --git a/src/service.h b/src/service.h
index 3801e84..cab18c2 100644
--- a/src/service.h
+++ b/src/service.h
@@ -99,6 +99,10 @@ struct Service {
         usec_t timeout_usec;
 
         dual_timestamp watchdog_timestamp;
+        usec_t watchdog_restart_usec;
+        usec_t watchdog_reboot_usec;
+        Watch watchdog_restart_watch;
+        Watch watchdog_reboot_watch;
 
         ExecCommand* exec_command[_SERVICE_EXEC_COMMAND_MAX];
         ExecContext exec_context;
-- 
1.7.5.4



More information about the systemd-devel mailing list