[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