diff options
author | Jo-Philipp Wich <jow@openwrt.org> | 2009-05-12 22:16:24 +0000 |
---|---|---|
committer | Jo-Philipp Wich <jow@openwrt.org> | 2009-05-12 22:16:24 +0000 |
commit | 89afc3a1d5b86c064e7da32c542d931cb73eca2b (patch) | |
tree | cd733661220fd539d93c1c3156dc1e2a2318d345 /contrib/package/freifunk-watchdog/src | |
parent | 153d28729894409f19c2455df9ea158ddd1815cd (diff) |
contrib/package/freifunk-watchdog:
- poll /dev/watchdog if available
- also monitor dropbear
Diffstat (limited to 'contrib/package/freifunk-watchdog/src')
-rw-r--r-- | contrib/package/freifunk-watchdog/src/watchdog.c | 93 | ||||
-rw-r--r-- | contrib/package/freifunk-watchdog/src/watchdog.h | 13 |
2 files changed, 91 insertions, 15 deletions
diff --git a/contrib/package/freifunk-watchdog/src/watchdog.c b/contrib/package/freifunk-watchdog/src/watchdog.c index c269f22d0..5caf6d5e7 100644 --- a/contrib/package/freifunk-watchdog/src/watchdog.c +++ b/contrib/package/freifunk-watchdog/src/watchdog.c @@ -131,6 +131,24 @@ static int find_process(const char *name) return -1; } +/* Get the 5 minute load average */ +static double find_loadavg(void) +{ + int fd; + char buffer[10]; + double load = 0.00; + + if( (fd = open("/proc/loadavg", O_RDONLY)) > -1 ) + { + if( read(fd, buffer, sizeof(buffer)) == sizeof(buffer) ) + load = atof(&buffer[5]); + + close(fd); + } + + return load; +} + /* Check if given uci file was updated */ static int check_uci_update(const char *config, time_t *mtime) { @@ -185,7 +203,7 @@ static void load_wifi_uci_add_iface(const char *section, struct uci_itr_ctx *itr val++; } } - + if( val == 3 ) { syslog(LOG_INFO, "Monitoring %s: bssid=%s channel=%d", @@ -240,6 +258,8 @@ static wifi_tuple_t * load_wifi_uci(wifi_tuple_t *ifs, time_t *modtime) static int do_daemon(void) { int iwfd; + int wdfd; + int wdtrigger = 1; int channel; char bssid[18]; @@ -248,32 +268,44 @@ static int do_daemon(void) int restart_wifi = 0; int restart_cron = 0; + int restart_sshd = 0; + int loadavg_panic = 0; openlog(SYSLOG_IDENT, 0, LOG_DAEMON); //daemon(1, 1); if( (iwfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1 ) { - perror("Can not open wireless control socket"); + syslog(LOG_ERR, "Can not open wireless control socket: %s", + strerror(errno)); + return 1; } + if( (wdfd = open(WATCH_DEVICE, O_WRONLY)) > -1 ) + { + syslog(LOG_INFO, "Opened %s - polling each %i seconds", + WATCH_DEVICE, INTERVAL); + } + while( 1 ) { - if( (ifs = load_wifi_uci(ifs, &modtime)) == NULL ) - { - printf("Can not load wireless uci. File corrupt?\n"); - return 1; - } + /* Check average load */ + if( find_loadavg() >= LOAD_TRESHOLD ) + loadavg_panic++; + else + loadavg_panic = 0; /* Check crond */ if( find_process("crond") < 0 ) - { - syslog(LOG_WARNING, "The crond process died, restarting"); - restart_cron++; - } + restart_cron++; + + /* Check SSHd */ + if( find_process("dropbear") < 0 ) + restart_sshd++; /* Check wireless interfaces */ + ifs = load_wifi_uci(ifs, &modtime); for( curif = ifs; curif; curif = curif->next ) { /* Get current channel and bssid */ @@ -300,7 +332,7 @@ static int do_daemon(void) } else { - syslog(LOG_WARNING, "Requested interface %s not present", curif->ifname); + syslog(LOG_WARNING, "Requested interface %s not present", curif->ifname); } } @@ -309,7 +341,7 @@ static int do_daemon(void) if( restart_wifi >= HYSTERESIS ) { restart_wifi = 0; - syslog(LOG_WARNING, "Restarting wireless"); + syslog(LOG_WARNING, "Channel or BSSID mismatch on wireless interface, restarting"); EXEC(WIFI_ACTION); } @@ -317,13 +349,44 @@ static int do_daemon(void) if( restart_cron >= HYSTERESIS ) { restart_cron = 0; - syslog(LOG_WARNING, "Restarting crond process"); - EXEC(CRON_ACTION); + syslog(LOG_WARNING, "The cron process died, restarting"); + EXEC(CRON_ACTION); + } + + /* SSHd restart required? */ + if( restart_sshd >= HYSTERESIS ) + { + restart_sshd = 0; + syslog(LOG_WARNING, "The ssh process died, restarting"); + EXEC(SSHD_ACTION); + } + + /* Is there a load problem? */ + if( loadavg_panic >= HYSTERESIS ) + { + syslog(LOG_EMERG, "Critical system load level, triggering reset!"); + + /* Try watchdog, fall back to reboot */ + if( wdfd > -1 ) + ioctl(wdfd, WDIOC_SETTIMEOUT, &wdtrigger); + else + EXEC(LOAD_ACTION); } + /* Reset watchdog timer */ + if( wdfd > -1 ) + write(wdfd, '\0', 1); + sleep(INTERVAL); } + if( wdfd > -1 ) + { + syslog(LOG_INFO, "Stopping watchdog timer"); + write(wdfd, WATCH_SHUTDOWN, 1); + close(wdfd); + } + closelog(); return 0; } diff --git a/contrib/package/freifunk-watchdog/src/watchdog.h b/contrib/package/freifunk-watchdog/src/watchdog.h index 7de24210a..f0d620999 100644 --- a/contrib/package/freifunk-watchdog/src/watchdog.h +++ b/contrib/package/freifunk-watchdog/src/watchdog.h @@ -31,6 +31,8 @@ #include <sys/stat.h> #include <sys/ioctl.h> #include <sys/socket.h> +#include <linux/types.h> +#include <linux/watchdog.h> #include "ucix.h" #include "wireless.22.h" @@ -51,6 +53,17 @@ /* Crond error action */ #define CRON_ACTION "/etc/init.d/cron", "/etc/init.d/cron", "restart" +/* SSHd error action */ +#define SSHD_ACTION "/etc/init.d/dropbear", "/etc/init.d/dropbear", "restart" + +/* Watchdog device */ +#define WATCH_DEVICE "/dev/watchdog" +#define WATCH_SHUTDOWN 'V' + +/* System load error action and treshold */ +#define LOAD_TRESHOLD 5.00 +#define LOAD_ACTION "/sbin/reboot" + /* Fallback binary name (passed by makefile) */ #ifndef BINARY #define BINARY "ffwatchd" |