Modify

Opened 10 years ago

Closed 3 years ago

#2270 closed defect (wontfix)

[PATCH] simple watchdog daemon (great for soekris et. al.)

Reported by: knox Owned by: developers
Priority: normal Milestone: Barrier Breaker 14.07
Component: packages Version: Trunk
Keywords: Cc:

Description

Simple Watchdog-Daemon with signal-Handling and syslog messaging.
You can configure the trigger-interval, the device-name and the reset-timeout.
I use it on soekris devices which come with a hardware watchdog.

Index: package/utils/watchdogd/files/etc/config/watchdogd
===================================================================
--- package/utils/watchdogd/files/etc/config/watchdogd	(Revision 0)
+++ package/utils/watchdogd/files/etc/config/watchdogd	(Revision 0)
@@ -0,0 +1,6 @@
+config watchdogd general
+	option trigger	
+	option timeout	
+	option device	
+	option driver	
+
Index: package/utils/watchdogd/files/etc/init.d/watchdogd
===================================================================
--- package/utils/watchdogd/files/etc/init.d/watchdogd	(Revision 0)
+++ package/utils/watchdogd/files/etc/init.d/watchdogd	(Revision 0)
@@ -0,0 +1,34 @@
+#!/bin/sh /etc/rc.common
+START=20
+. /lib/config/uci.sh
+uci_load watchdogd
+start () {
+	trigger=$(uci get watchdogd.general.trigger)
+	timeout=$(uci get watchdogd.general.timeout)
+	device=$(uci get watchdogd.general.device)
+	driver=$(uci get watchdogd.general.driver)
+	watchdogd_args=""
+	if [ $trigger ]; then
+		watchdogd_args=${watchdogd_args}'-t '$trigger' '
+	fi
+	if [ $timeout ]; then
+		watchdogd_args=${watchdogd_args}'-r '$timeout' '
+	fi
+	if [ $device ]; then
+		watchdogd_args=${watchdogd_args}'-d '$device' '
+	fi
+	if [ $driver ]; then
+		watchdogd_args=${watchdogd_args}'-s '$driver' '
+	fi
+	watchdogd $watchdogd_args >/dev/null 2>&1
+}
+
+restart () {
+	$0 stop
+	sleep 3
+	$0 start
+}
+        
+stop () {
+	killall watchdogd
+}
Index: package/utils/watchdogd/src/watchdogd.c
===================================================================
--- package/utils/watchdogd/src/watchdogd.c	(Revision 0)
+++ package/utils/watchdogd/src/watchdogd.c	(Revision 0)
@@ -0,0 +1,325 @@
+/*
+ * Simple Watchdog-Daemon with signal-Handling and syslog messaging
+ * You can configure the trigger-interval, the device-name and
+ * the reset-timeout.
+ * Not every watchdog-driver allows the programming of the reset-timeout
+ * so please be carefull about this option
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * Version 2 as published by the Free Software Foundation.
+ *
+ * I don't accept liability nor provide warranty for this Software.
+ * This material is provided "AS-IS" and at no charge.
+ *
+ * Version History
+ *
+ * 0.1     rresch    Initial Release
+ * 0.2     rresch    Fixed several Bugs
+ *
+ *
+ * rresch  (c) 2006 Robert Resch <rresch@gmx.de>
+ *
+ */
+
+#include <stdlib.h>
+#include <linux/types.h>
+#include <linux/watchdog.h>
+#include <sys/ioctl.h>
+#include <string.h>
+#include <unistd.h>
+#include <signal.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <syslog.h>
+#define version "0.2"
+
+volatile int shutdown_flag=0;
+volatile int wd_trigger_enable=1;
+
+/* Set Watchdog-Clean-Exit-Flag */
+static void handlerterm(int signum)
+{
+        shutdown_flag = 1;
+}
+
+/* Toggle Watchdog-Disable Flag */
+static void handlerhup(int signum)
+{
+        wd_trigger_enable=!wd_trigger_enable;
+}
+
+int main(int argc, const char *argv[])
+{
+  /* Signal Handler for SIGTERM */
+  struct sigaction sa1;
+  /* Signal Handler for SIGHUP */
+  struct sigaction sa2;
+  /* Structure for holding some information about the watchdog we found */
+  struct watchdog_info ident;
+  /* File-Descriptor for Watchdog */
+  int fd;
+  /* Temporary used File-Descriptor for configuring wd1100 Watchdog */
+  int fd1;
+  /* Default-Sleeptime */
+  int sleeptime=1;
+  /* Reset-time 0=don't change */
+  int resettime=0;
+  /* Try configuring wd1100 special files in /proc/... */
+  int wd1100hack=0;
+  /* Set if wd1100 is auto-detected */
+  int wd1100detected=0;
+  /* set to one if watchdog-ident was ok */
+  int wdidentok=0;
+  /* Flag signalling that the help-message should be printed */
+  int help=0;
+  /* Counter for universal usage */
+  int i;
+  /* Buffer used for converting a integer to a ascii value */
+  char buf[16];
+  /* base-name of binary */
+  char *progname;
+  /* Device for watchdog */
+  char *wd_devicename="/dev/watchdog";
+  /* this 2 Variables are only used for Unicode-Compatibility */
+  const char *zero="0\n";
+  const char *one="1\n";
+  /* return-value */
+  int retval=0;
+
+  /* extract programm-binary-name from full-path in argv[0] */
+  progname=(char *) argv[0];
+  for (i=0;argv[0][i];i++)
+  {
+    if (argv[0][i] == '/')
+    {
+      progname=(char *) argv[0]+i+1;
+    }
+  }
+
+  /* parse commandline for parameters */
+  for (i=1;i<argc;i++)
+  {
+    /* Parameter trigger-interval */
+    if (!strncmp("-t",argv[i],2) && i+1<argc )
+    {
+      i++;
+      if (atoi(argv[i])>0)
+      {
+        sleeptime=atoi(argv[i]);
+      }
+      else
+      {
+        printf("Invalid trigger-interval\n");
+        help=1;
+      }
+    }
+    /* Parameter reset-timeout */
+    if (!strncmp("-r",argv[i],2) && i+1<argc )
+    {
+      i++;
+      if (atoi(argv[i])>0)
+      {
+        resettime=atoi(argv[i]);
+      }
+      else
+      {
+        printf("Invalid reset-timout\n");
+        help=1;
+      }
+    }
+    /* Parameter Device */
+    if (!strncmp("-d",argv[i],2) && i+1<argc )
+    {
+      i++;
+      wd_devicename=(char *) argv[i];
+    }
+    /* Manually activate wd1100 Hack */
+    /* This watchdog doesn't implement all IOCTL but is configured by /proc... Filesystem */
+    if (!strncmp("-s",argv[i],2))
+    {
+      wd1100hack=1;
+    }
+    /* Help Message */
+    if (!strncmp("--help",argv[i],6) || !strncmp("--ver",argv[i],5))
+    {
+      help = 1;
+    }
+  }
+
+  /* Reset-Timeout must be greater than trigger interval */
+  if (resettime)
+  {
+    if (resettime <= sleeptime)
+    {
+      printf("reset-timeout may not be less than or equal to trigger-interval\n");
+      help=1;
+    }
+  }
+
+  /* Print help and exit */
+  if (help)
+  {
+    printf("Watchdogd Version %s (c) Robert Resch <rresch@gmx.de>\n",version);
+    printf("Usage: %s [options]\n",progname);
+    printf("Options:\n");
+    printf("  -t <n>     trigger the watchdog every <n> seconds\n");
+    printf("             default: 1\n");
+    printf("  -d <dev>   use <dev> as watchdog-device\n");
+    printf("             default: /dev/watchdog\n");
+    printf("  -r <n>     set watchdog-reset timeout to <n> seconds\n");
+    printf("             default: use watchdog-driver default\n");
+    printf("  -s         configure watchdog-driver via /proc/sys/dev/wd/*\n");
+    printf("  --help\n  --version  this text\n");
+    exit(0);
+  }
+
+  /* prepare signal handlers */
+  sa1.sa_handler = handlerterm;
+  sa2.sa_handler = handlerhup;
+  sigemptyset(&sa1.sa_mask);
+  sigemptyset(&sa2.sa_mask);
+  sa1.sa_flags = SA_RESTART;
+  sa2.sa_flags = SA_RESTART;
+  
+  /* open Syslog */
+  openlog(progname, LOG_PID|LOG_CONS , LOG_DAEMON);
+
+  /* install signal handlers and start watchdog if successul */
+  if (sigaction(SIGTERM, &sa1, NULL) != -1 && sigaction(SIGHUP, &sa2, NULL) != -1)
+  {
+    /* we can only trigger a existing watchdog */
+    if ((fd=open(wd_devicename,O_WRONLY)) != -1)
+    {
+      /* write start-message to syslog */
+      syslog(LOG_INFO,"using watchdog-device: %s", wd_devicename);
+      /* IOCTL to get ident Information and other info from watchdog-device */
+      if (ioctl(fd, WDIOC_GETSUPPORT, &ident) != -1)
+      {
+        syslog(LOG_INFO,"found watchdog: %s", ident.identity);
+        wdidentok=1;
+        /* If watchdog has this identity then we need to activate the wd1100 hack */
+        if (!strncmp("NSC SC1x00 WD",ident.identity,13))
+        {
+          syslog(LOG_INFO,"enabling special support for watchdog-driver");
+          wd1100hack=1;
+          wd1100detected=1;
+        }
+      }
+      else
+      {
+        syslog(LOG_WARNING,"could not detect watchdog");
+      }
+
+      /* Only set timeout if >0 */
+      if (resettime)
+      {
+        i=0;
+        if (wdidentok)
+        {
+          if (ident.options&WDIOF_SETTIMEOUT)
+          {
+            ioctl(fd, WDIOC_SETTIMEOUT, &resettime);
+            i=1;
+          }
+        }
+        if (wd1100hack)
+        {
+          if ((fd1=open("/proc/sys/dev/wd/timeout",O_WRONLY)) != -1)
+          {
+            sprintf(buf,"%d\n",resettime);
+            write (fd1,buf,strlen(buf));
+            close(fd1);
+            i=1;
+          }
+        }
+        if (i)
+        {
+          syslog(LOG_INFO,"watchdog timeout set to %d second(s)", resettime);
+        }
+        else
+        {
+          syslog(LOG_WARNING,"could not set watchdog timeout");
+        }
+      }
+      /* Set graceful Flag to 0 -> abnormal termination of this program triggers reset */
+      if (wd1100hack)
+      {
+        if ((fd1=open("/proc/sys/dev/wd/graceful",O_WRONLY)) != -1)
+        {
+          write (fd1,zero,strlen(zero));
+          close(fd1);
+        }
+      }
+      syslog(LOG_INFO,"triggering watchdog every %d second(s)",sleeptime);
+
+      /* daemon() -> detach from console */
+      if (daemon(1,1) == -1)
+      {
+        syslog(LOG_ERR, "cannot detach from console");
+        shutdown_flag=1;
+   	retval=3;
+      }
+
+      /* Main Watchdog-Loop */
+      while (!shutdown_flag)
+      {
+        /* watchdog-triggering disabled? */
+        if (wd_trigger_enable)
+        {
+          /* Reset watchdog-timer */
+          write(fd,"\0",1);
+          fsync(fd);
+          for (i=0;i<sleeptime&&!shutdown_flag&&wd_trigger_enable;i++) sleep(1);
+        }
+        else
+        {
+          syslog(LOG_WARNING,"disabled watchdog triggering - expect hw-reset");
+          /* do nothing for one second */
+          /* and wait for reset or another SIGHUP to re-enable */
+          while (!wd_trigger_enable && !shutdown_flag) sleep(1);
+          syslog(LOG_WARNING,"re-enabled watchdog triggering");
+        }
+      }
+      /* End of Main Watchdog-Loop */
+      
+      /* try a clean shutdown */
+      if (wd1100detected)
+      {
+        syslog(LOG_WARNING,"disabling watchdog");
+      }
+      else
+      {
+        syslog(LOG_WARNING,"disabling watchdog - some hardware doesn't allow to be disabled!");
+      }
+      /* Set graceful-flag to '1' -> disable Watchdog after close() */
+      if (wd1100hack)
+      {
+        if ((fd1=open("/proc/sys/dev/wd/graceful",O_WRONLY)) != -1)
+        {
+          write (fd1,one,strlen(one));
+          close(fd1);
+        }
+      }
+      /* send ioctl to safely disable watchdog card */
+      ioctl(fd, WDIOC_SETOPTIONS, WDIOS_DISABLECARD);
+      /* write 'magic' to watchdog-device - most watchdog-drivers need it to disable */
+      /* needs to be the last Character before close() */
+      write(fd,"V",1);
+      close(fd);
+      syslog(LOG_INFO,"exiting");
+    }
+    else
+    {
+      syslog(LOG_ERR,"cannot open Watchdog-device: %s - exiting\n",wd_devicename);
+      retval=1;
+    }
+  }
+  else
+  {
+    syslog(LOG_ERR,"cannot install signal Handlers - exiting");
+    retval=2;
+  }
+  closelog();
+  return (retval);
+}
Index: package/utils/watchdogd/Makefile
===================================================================
--- package/utils/watchdogd/Makefile	(Revision 0)
+++ package/utils/watchdogd/Makefile	(Revision 0)
@@ -0,0 +1,60 @@
+# 
+# Copyright (C) 2006 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+# $Id: Makefile  $
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=watchdogd
+PKG_VERSION:=0.2
+PKG_RELEASE:=1
+
+PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)_$(PKG_VERSION)
+
+PKG_INSTALL_DIR:=$(PKG_BUILD_DIR)/ipkg-install
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/watchdogd
+  SECTION:=utils
+  CATEGORY:=Utilities
+  TITLE:=Simple Watchdog-Daemon
+  DESCRIPTION:=\
+	Simple Watchdog-Daemon with signal-Handling and syslog messaging. \\\
+	You can configure the trigger-interval, the device-name and \\\
+	the reset-timeout. \\\
+	Not every watchdog-driver allows the programming of the reset-timeout \\\
+	so please be carefull about this option. \\\
+	This daemon was taken from the on(e) disk distribution fli4l.
+  URL:=http://www.fli4l.de
+  MAINTAINER:=mickey <mickey@netfreaks.org>
+endef
+
+define Build/Prepare
+	mkdir -p $(PKG_BUILD_DIR)
+	$(CP) -f src/watchdogd.c $(PKG_BUILD_DIR)/
+endef
+
+define Build/Configure
+endef
+
+define Build/Compile
+	$(MAKE_VARS) \
+	$(MAKE) -C $(PKG_BUILD_DIR)/$(MAKE_PATH) \
+		$(MAKE_FLAGS) \
+		$(1);
+	mkdir -p $(PKG_INSTALL_DIR)/usr/sbin/
+	$(CP) -f $(PKG_BUILD_DIR)/watchdogd $(PKG_INSTALL_DIR)/usr/sbin/
+endef
+
+define Package/watchdogd/install
+	$(INSTALL_DIR) $(1)/usr/sbin $(1)/etc/config $(1)/etc/init.d
+	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/watchdogd $(1)/usr/sbin/
+	$(INSTALL_BIN) ./files/etc/init.d/watchdogd $(1)/etc/init.d
+	$(INSTALL_DATA) ./files/etc/config/watchdogd $(1)/etc/config
+endef
+
+$(eval $(call BuildPackage,watchdogd))

Attachments (0)

Change History (4)

comment:1 Changed 9 years ago by florian

  • Resolution set to wontfix
  • Status changed from new to closed

busybox provides its watchdog daemon capable of using a /dev/watchdog which is the standard kernel/user space daemon to use

comment:2 Changed 4 years ago by jow

  • Milestone changed from Attitude Adjustment 12.09 to Barrier Breaker 14.07

Milestone Attitude Adjustment 12.09 deleted

comment:3 Changed 3 years ago by anonymous

  • Resolution wontfix deleted
  • Status changed from closed to reopened

comment:4 Changed 3 years ago by blogic

  • Resolution set to wontfix
  • Status changed from reopened to closed
  • Version set to Trunk

Add Comment

Modify Ticket

Action
as closed .
The resolution will be deleted. Next status will be 'reopened'.
Author


E-mail address and user name can be saved in the Preferences.

 
Note: See TracTickets for help on using tickets.