[systemd-devel] [PATCH 4/4] WIP: add basic watchdog daemon

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


---
 Makefile.am                        |   21 ++++++-
 src/99-systemd.rules.in            |    2 +
 src/watchdogd.c                    |  119 ++++++++++++++++++++++++++++++++++++
 units/systemd-watchdogd.service.in |   16 +++++
 4 files changed, 156 insertions(+), 2 deletions(-)
 create mode 100644 src/watchdogd.c
 create mode 100644 units/systemd-watchdogd.service.in

diff --git a/Makefile.am b/Makefile.am
index 570b6be..3959526 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -173,7 +173,8 @@ rootlibexec_PROGRAMS = \
 	systemd-detect-virt \
 	systemd-sysctl \
         systemd-logind \
-        systemd-uaccess
+        systemd-uaccess \
+	systemd-watchdogd
 
 if ENABLE_BINFMT
 rootlibexec_PROGRAMS += \
@@ -414,6 +415,7 @@ nodist_systemunit_DATA = \
 	units/systemd-ask-password-wall.service \
 	units/systemd-ask-password-console.service \
 	units/systemd-sysctl.service \
+	units/systemd-watchdogd.service \
 	units/halt.service \
 	units/poweroff.service \
 	units/reboot.service \
@@ -477,6 +479,7 @@ EXTRA_DIST = \
 	units/systemd-ask-password-wall.service.in \
 	units/systemd-ask-password-console.service.in \
 	units/systemd-sysctl.service.in \
+	units/systemd-watchdogd.service.in \
 	units/halt.service.in \
 	units/poweroff.service.in \
 	units/reboot.service.in \
@@ -1307,6 +1310,19 @@ systemd_kmsg_syslogd_LDADD = \
 	libsystemd-basic.la \
 	libsystemd-daemon.la
 
+systemd_watchdogd_SOURCES = \
+	src/watchdogd.c \
+	src/dbus-common.c
+
+systemd_watchdogd_CFLAGS = \
+	$(AM_CFLAGS) \
+	$(DBUS_CFLAGS)
+
+systemd_watchdogd_LDADD = \
+	libsystemd-basic.la \
+	libsystemd-daemon.la \
+	$(DBUS_LIBS)
+
 systemctl_SOURCES = \
 	src/systemctl.c \
 	src/utmp-wtmp.c \
@@ -1896,7 +1912,8 @@ if ENABLE_LOCALED
 endif
 	( cd $(DESTDIR)$(systemunitdir)/basic.target.wants && \
 		rm -f systemd-tmpfiles-clean.timer && \
-		$(LN_S) ../systemd-tmpfiles-clean.timer systemd-tmpfiles-clean.timer )
+		$(LN_S) ../systemd-tmpfiles-clean.timer systemd-tmpfiles-clean.timer && \
+		$(LN_S) ../systemd-watchdogd.service systemd-watchdogd.service )
 	( cd $(DESTDIR)$(dbussessionservicedir) && \
 		rm -f org.freedesktop.systemd1.service && \
 		$(LN_S) ../system-services/org.freedesktop.systemd1.service org.freedesktop.systemd1.service )
diff --git a/src/99-systemd.rules.in b/src/99-systemd.rules.in
index b2481ae..8e9dfcd 100644
--- a/src/99-systemd.rules.in
+++ b/src/99-systemd.rules.in
@@ -12,6 +12,8 @@ SUBSYSTEM=="tty", KERNEL=="tty[a-zA-Z]*|hvc*|xvc*|hvsi*", TAG+="systemd"
 
 KERNEL=="vport*", TAG+="systemd"
 
+KERNEL=="watchdog", TAG+="systemd"
+
 SUBSYSTEM=="block", KERNEL!="ram*|loop*", TAG+="systemd"
 SUBSYSTEM=="block", KERNEL!="ram*|loop*", ENV{DM_UDEV_DISABLE_OTHER_RULES_FLAG}=="1", ENV{SYSTEMD_READY}="0"
 
diff --git a/src/watchdogd.c b/src/watchdogd.c
new file mode 100644
index 0000000..44251cc
--- /dev/null
+++ b/src/watchdogd.c
@@ -0,0 +1,119 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+  This file is part of systemd.
+
+  Copyright 2010 Michael Olbrich
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <dbus/dbus.h>
+
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <time.h>
+#include <string.h>
+#include <errno.h>
+#include <linux/watchdog.h>
+
+#include "log.h"
+#include "util.h"
+#include "dbus-common.h"
+#include "sd-daemon.h"
+
+int main(int argc, char *argv[]) {
+        int fd, ret;
+        struct timespec ts;
+        DBusConnection *bus = NULL;
+        DBusMessage *m, *reply = NULL;
+        DBusError error;
+        DBusMessageIter iter, sub;
+        usec_t watchdog_usec, now_usec;
+        const char *iface = "org.freedesktop.systemd1.Manager";
+        const char *property = "WatchdogRebootTimestampMonotonic";
+        int timeout = 10;
+        usec_t reboot_delay_usec = 1 * USEC_PER_SEC;
+
+        log_set_target(LOG_TARGET_AUTO);
+        log_parse_environment();
+        log_open();
+
+        umask(0022);
+
+        dbus_error_init(&error);
+
+        if ((ret = bus_connect(DBUS_BUS_SYSTEM, &bus, NULL, &error)) < 0) {
+                log_error("Failed to get D-Bus connection: %s", bus_error_message(&error));
+                return 1;
+        }
+        if (!(m = dbus_message_new_method_call("org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.DBus.Properties", "Get"))) {
+                log_error("Could not allocate message.");
+                return 1;
+        }
+        if (!dbus_message_append_args(m,
+                                      DBUS_TYPE_STRING, &iface,
+                                      DBUS_TYPE_STRING, &property,
+                                      DBUS_TYPE_INVALID)) {
+                log_error("Could not attach target and flag information to message.");
+                return 1;
+        }
+
+        if ((fd = open("/dev/watchdog", O_RDWR)) < 0) {
+                log_error("Could not open /dev/watchdog: %s", strerror(errno));
+                return 1;
+        }
+
+        if (ioctl(fd, WDIOC_SETTIMEOUT, &timeout) < 0) {
+                log_error("Failed to set watchdog timeout: %s", strerror(errno));
+                return 1;
+        }
+        log_info("Watchdog timeout set to %ds", timeout);
+        sd_notify(false,
+                  "READY=1\n"
+                  "STATUS=Watchdog started.");
+
+        timeout /= 2;
+        clock_gettime(CLOCK_MONOTONIC, &ts);
+        while (true) {
+                now_usec = timespec_load(&ts);
+                clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &ts, 0);
+                ts.tv_sec += timeout;
+
+                if (reply)
+                        dbus_message_unref(reply);
+
+                if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
+                        log_error("Error fetching reboot timestamp: %s", bus_error_message(&error));
+                        continue;
+                }
+                if (!dbus_message_iter_init(reply, &iter)) {
+                        log_error("Failed to parse reply (init).");
+                        continue;
+                }
+                dbus_message_iter_recurse(&iter, &sub);
+                if (bus_iter_get_basic_and_next(&sub, DBUS_TYPE_UINT64, &watchdog_usec, false) < 0) {
+                        log_error("Failed to parse reply (value).");
+                        continue;
+                }
+                if (watchdog_usec && ((watchdog_usec + reboot_delay_usec) < now_usec)) {
+                        log_error("Reboot failed: now = %llu, watchdog = %llu", now_usec, watchdog_usec);
+                        continue;
+                }
+                ioctl(fd, WDIOC_KEEPALIVE, 0);
+        }
+
+
+}
diff --git a/units/systemd-watchdogd.service.in b/units/systemd-watchdogd.service.in
new file mode 100644
index 0000000..643b3da
--- /dev/null
+++ b/units/systemd-watchdogd.service.in
@@ -0,0 +1,16 @@
+#  This file is part of systemd.
+#
+#  systemd is free software; you can redistribute it and/or modify it
+#  under the terms of the GNU General Public License as published by
+#  the Free Software Foundation; either version 2 of the License, or
+#  (at your option) any later version.
+
+[Unit]
+Description=Watchdog Daemon
+DefaultDependencies=no
+BindTo=dev-watchdog.device
+After=dev-watchdog.device
+
+[Service]
+Type=notify
+ExecStart=@rootlibexecdir@/systemd-watchdogd
-- 
1.7.5.4



More information about the systemd-devel mailing list