contrib/package/freifunk-watchdog: workaround CONFIG_WATCHDOG_NOWAYOUT, trap signals
authorJo-Philipp Wich <jow@openwrt.org>
Wed, 13 May 2009 00:19:03 +0000 (00:19 +0000)
committerJo-Philipp Wich <jow@openwrt.org>
Wed, 13 May 2009 00:19:03 +0000 (00:19 +0000)
contrib/package/freifunk-watchdog/src/watchdog.c
contrib/package/freifunk-watchdog/src/watchdog.h

index 5caf6d5..7bbb7c7 100644 (file)
 
 #include "watchdog.h"
 
+/* Global watchdog fd, required by signal handler */
+int wdfd = -1;
+
+/* Watchdog shutdown helper */
+static void shutdown_watchdog(int sig)
+{
+       static int wdelay = 3600;
+       static const char wshutdown = WATCH_SHUTDOWN;
+
+       if( wdfd > -1 )
+       {
+               syslog(LOG_INFO, "Stopping watchdog timer");
+               write(wdfd, &wshutdown, 1);
+
+               /* Older Kamikaze versions are compiled with
+                * CONFIG_WATCHDOG_NOWAYOUT=y, this can be
+                * harmful if we're in the middle of an upgrade.
+                * Increase the watchdog timeout to 3600 seconds
+                * here to avoid unplanned reboots. */
+               ioctl(wdfd, WDIOC_SETTIMEOUT, &wdelay);
+
+               close(wdfd);
+               wdfd = -1;
+       }
+
+       exit(0);
+}
+
 /* Get BSSID of given interface */
 static int iw_get_bssid(int iwfd, const char *ifname, char *bssid)
 {
@@ -257,11 +285,14 @@ static wifi_tuple_t * load_wifi_uci(wifi_tuple_t *ifs, time_t *modtime)
 /* Daemon implementation */
 static int do_daemon(void)
 {
+       static int wdtrigger = 1;
+       static int wdtimeout = INTERVAL * 2;
+       static const char wdkeepalive = WATCH_KEEPALIVE;
+
        int iwfd;
-       int wdfd;
-       int wdtrigger = 1;
        int channel;
        char bssid[18];
+       struct sigaction sa;
 
        wifi_tuple_t *ifs = NULL, *curif;
        time_t modtime = 0;
@@ -284,8 +315,21 @@ static int do_daemon(void)
 
        if( (wdfd = open(WATCH_DEVICE, O_WRONLY)) > -1 )
        {
-               syslog(LOG_INFO, "Opened %s - polling each %i seconds",
+               syslog(LOG_INFO, "Opened %s - polling every %i seconds",
                        WATCH_DEVICE, INTERVAL);
+
+               /* Install signal handler to halt watchdog on shutdown */
+               sa.sa_handler = shutdown_watchdog;
+               sa.sa_flags = SA_NOCLDWAIT | SA_RESTART;
+               sigaction(SIGHUP,  &sa, NULL);
+               sigaction(SIGINT,  &sa, NULL);
+               sigaction(SIGPIPE, &sa, NULL);
+               sigaction(SIGTERM, &sa, NULL);
+               sigaction(SIGUSR1, &sa, NULL);
+               sigaction(SIGUSR2, &sa, NULL);
+
+               /* Set watchdog timeout to twice the interval */
+               ioctl(wdfd, WDIOC_SETTIMEOUT, &wdtimeout);
        }
 
        while( 1 )
@@ -375,19 +419,14 @@ static int do_daemon(void)
 
                /* Reset watchdog timer */
                if( wdfd > -1 )
-                       write(wdfd, '\0', 1);
+                       write(wdfd, &wdkeepalive, 1);
 
                sleep(INTERVAL);
        }
 
-       if( wdfd > -1 )
-       {
-               syslog(LOG_INFO, "Stopping watchdog timer");
-               write(wdfd, WATCH_SHUTDOWN, 1);
-               close(wdfd);
-       }
-
+       shutdown_watchdog(0);
        closelog();
+
        return 0;
 }
 
index f0d6209..d3dc286 100644 (file)
@@ -28,6 +28,7 @@
 #include <fcntl.h>
 #include <math.h>
 #include <time.h>
+#include <signal.h>
 #include <sys/stat.h>
 #include <sys/ioctl.h>
 #include <sys/socket.h>
@@ -59,6 +60,7 @@
 /* Watchdog device */
 #define WATCH_DEVICE   "/dev/watchdog"
 #define WATCH_SHUTDOWN 'V'
+#define WATCH_KEEPALIVE        '\0'
 
 /* System load error action and treshold */
 #define LOAD_TRESHOLD  5.00