watchdogd.c (bc8b08782b087804a88176fad01492ff70855b7d) | watchdogd.c (4103b7652d1c438d04b360d0c81bae619b1b8259) |
---|---|
1/* 2 * Copyright (c) 2003 Sean M. Kelly <smkelly@FreeBSD.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 21 unchanged lines hidden (view full) --- 30 31#include <sys/types.h> 32__FBSDID("$FreeBSD$"); 33 34#include <sys/rtprio.h> 35#include <sys/stat.h> 36#include <sys/sysctl.h> 37#include <sys/time.h> | 1/* 2 * Copyright (c) 2003 Sean M. Kelly <smkelly@FreeBSD.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 21 unchanged lines hidden (view full) --- 30 31#include <sys/types.h> 32__FBSDID("$FreeBSD$"); 33 34#include <sys/rtprio.h> 35#include <sys/stat.h> 36#include <sys/sysctl.h> 37#include <sys/time.h> |
38#include <sys/watchdog.h> |
|
38 39#include <err.h> | 39 40#include <err.h> |
41#include <errno.h> 42#include <fcntl.h> 43#include <math.h> |
|
40#include <paths.h> 41#include <signal.h> 42#include <stdio.h> 43#include <stdlib.h> | 44#include <paths.h> 45#include <signal.h> 46#include <stdio.h> 47#include <stdlib.h> |
48#include <string.h> |
|
44#include <sysexits.h> 45#include <unistd.h> 46 47static void parseargs(int, char *[]); 48static void sighandler(int); 49static void watchdog_loop(void); 50static int watchdog_init(void); 51static int watchdog_onoff(int onoff); | 49#include <sysexits.h> 50#include <unistd.h> 51 52static void parseargs(int, char *[]); 53static void sighandler(int); 54static void watchdog_loop(void); 55static int watchdog_init(void); 56static int watchdog_onoff(int onoff); |
52static int watchdog_tickle(void); | 57static int watchdog_patpat(void); |
53static void usage(void); 54 55int debugging = 0; 56int end_program = 0; 57const char *pidfile = _PATH_VARRUN "watchdogd.pid"; 58int reset_mib[3]; 59size_t reset_miblen = 3; | 58static void usage(void); 59 60int debugging = 0; 61int end_program = 0; 62const char *pidfile = _PATH_VARRUN "watchdogd.pid"; 63int reset_mib[3]; 64size_t reset_miblen = 3; |
65u_int timeout = WD_TO_16SEC; 66u_int passive = 0; 67int is_daemon = 0; 68int fd = -1; 69int nap = 1; 70char *test_cmd = NULL; |
|
60 61/* 62 * Periodically write to the debug.watchdog.reset sysctl OID 63 * to keep the software watchdog from firing. 64 */ 65int 66main(int argc, char *argv[]) 67{ --- 8 unchanged lines hidden (view full) --- 76 rtp.type = RTP_PRIO_REALTIME; 77 rtp.prio = 0; 78 if (rtprio(RTP_SET, 0, &rtp) == -1) 79 err(EX_OSERR, "rtprio"); 80 81 if (watchdog_init() == -1) 82 errx(EX_SOFTWARE, "unable to initialize watchdog"); 83 | 71 72/* 73 * Periodically write to the debug.watchdog.reset sysctl OID 74 * to keep the software watchdog from firing. 75 */ 76int 77main(int argc, char *argv[]) 78{ --- 8 unchanged lines hidden (view full) --- 87 rtp.type = RTP_PRIO_REALTIME; 88 rtp.prio = 0; 89 if (rtprio(RTP_SET, 0, &rtp) == -1) 90 err(EX_OSERR, "rtprio"); 91 92 if (watchdog_init() == -1) 93 errx(EX_SOFTWARE, "unable to initialize watchdog"); 94 |
84 if (watchdog_onoff(1) == -1) 85 exit(EX_SOFTWARE); | 95 if (is_daemon) { 96 if (watchdog_onoff(1) == -1) 97 exit(EX_SOFTWARE); |
86 | 98 |
87 if (debugging == 0 && daemon(0, 0) == -1) { 88 watchdog_onoff(0); 89 err(EX_OSERR, "daemon"); 90 } | 99 if (debugging == 0 && daemon(0, 0) == -1) { 100 watchdog_onoff(0); 101 err(EX_OSERR, "daemon"); 102 } |
91 | 103 |
92 signal(SIGHUP, SIG_IGN); 93 signal(SIGINT, sighandler); 94 signal(SIGTERM, sighandler); | 104 signal(SIGHUP, SIG_IGN); 105 signal(SIGINT, sighandler); 106 signal(SIGTERM, sighandler); |
95 | 107 |
96 fp = fopen(pidfile, "w"); 97 if (fp != NULL) { 98 fprintf(fp, "%d\n", getpid()); 99 fclose(fp); 100 } | 108 fp = fopen(pidfile, "w"); 109 if (fp != NULL) { 110 fprintf(fp, "%d\n", getpid()); 111 fclose(fp); 112 } |
101 | 113 |
102 watchdog_loop(); | 114 watchdog_loop(); |
103 | 115 |
104 /* exiting */ 105 watchdog_onoff(0); 106 unlink(pidfile); 107 return (EX_OK); | 116 /* exiting */ 117 watchdog_onoff(0); 118 unlink(pidfile); 119 return (EX_OK); 120 } else { 121 if (passive) 122 timeout |= WD_PASSIVE; 123 else 124 timeout |= WD_ACTIVE; 125 if (watchdog_patpat() < 0) 126 err(EX_OSERR, "patting the dog"); 127 return (EX_OK); 128 } |
108} 109 110/* 111 * Catch signals and begin shutdown process. 112 */ 113static void 114sighandler(int signum) 115{ --- 4 unchanged lines hidden (view full) --- 120 121/* 122 * Locate the OID for the 'debug.watchdog.reset' sysctl setting. 123 * Upon finding it, do an initial reset on the watchdog. 124 */ 125static int 126watchdog_init() 127{ | 129} 130 131/* 132 * Catch signals and begin shutdown process. 133 */ 134static void 135sighandler(int signum) 136{ --- 4 unchanged lines hidden (view full) --- 141 142/* 143 * Locate the OID for the 'debug.watchdog.reset' sysctl setting. 144 * Upon finding it, do an initial reset on the watchdog. 145 */ 146static int 147watchdog_init() 148{ |
128 int error; | |
129 | 149 |
130 error = sysctlnametomib("debug.watchdog.reset", reset_mib, 131 &reset_miblen); 132 if (error == -1) { 133 warn("could not find reset OID"); 134 return (error); 135 } 136 return watchdog_tickle(); | 150 fd = open("/dev/" _PATH_WATCHDOG, O_RDWR); 151 if (fd >= 0) 152 return (0); 153 warn("Could not open watchdog device"); 154 return (-1); |
137} 138 139/* 140 * Main program loop which is iterated every second. 141 */ 142static void 143watchdog_loop(void) 144{ 145 struct stat sb; 146 int failed; 147 148 while (end_program == 0) { 149 failed = 0; 150 | 155} 156 157/* 158 * Main program loop which is iterated every second. 159 */ 160static void 161watchdog_loop(void) 162{ 163 struct stat sb; 164 int failed; 165 166 while (end_program == 0) { 167 failed = 0; 168 |
151 failed = stat("/etc", &sb); | 169 if (test_cmd != NULL) 170 failed = system(test_cmd); 171 else 172 failed = stat("/etc", &sb); |
152 153 if (failed == 0) | 173 174 if (failed == 0) |
154 watchdog_tickle(); 155 sleep(1); | 175 watchdog_patpat(); 176 sleep(nap); |
156 } 157} 158 159/* 160 * Reset the watchdog timer. This function must be called periodically 161 * to keep the watchdog from firing. 162 */ 163int | 177 } 178} 179 180/* 181 * Reset the watchdog timer. This function must be called periodically 182 * to keep the watchdog from firing. 183 */ 184int |
164watchdog_tickle(void) | 185watchdog_patpat(void) |
165{ 166 | 186{ 187 |
167 return sysctl(reset_mib, reset_miblen, NULL, NULL, NULL, 0); | 188 return ioctl(fd, WDIOCPATPAT, &timeout); |
168} 169 170/* 171 * Toggle the kernel's watchdog. This routine is used to enable and 172 * disable the watchdog. 173 */ 174static int 175watchdog_onoff(int onoff) 176{ | 189} 190 191/* 192 * Toggle the kernel's watchdog. This routine is used to enable and 193 * disable the watchdog. 194 */ 195static int 196watchdog_onoff(int onoff) 197{ |
177 int mib[3]; 178 int error; 179 size_t len; | |
180 | 198 |
181 len = 3; 182 183 error = sysctlnametomib("debug.watchdog.enabled", mib, &len); 184 if (error == 0) 185 error = sysctl(mib, len, NULL, NULL, &onoff, sizeof(onoff)); 186 187 if (error == -1) { 188 warn("could not %s watchdog", 189 (onoff > 0) ? "enable" : "disable"); 190 return (error); 191 } 192 return (0); | 199 if (onoff) 200 timeout |= WD_ACTIVE; 201 else 202 timeout &= ~WD_ACTIVE; 203 return watchdog_patpat(); |
193} 194 195/* 196 * Tell user how to use the program. 197 */ 198static void 199usage() 200{ | 204} 205 206/* 207 * Tell user how to use the program. 208 */ 209static void 210usage() 211{ |
201 fprintf(stderr, "usage: watchdogd [-d] [-I file]\n"); | 212 if (is_daemon) 213 fprintf(stderr, "usage: watchdogd [-d] [-e cmd] [-I file]\n"); 214 else 215 fprintf(stderr, "usage: watchdog [-d] [-t]\n"); |
202 exit(EX_USAGE); 203} 204 205/* 206 * Handle the few command line arguments supported. 207 */ 208static void 209parseargs(int argc, char *argv[]) 210{ 211 int c; | 216 exit(EX_USAGE); 217} 218 219/* 220 * Handle the few command line arguments supported. 221 */ 222static void 223parseargs(int argc, char *argv[]) 224{ 225 int c; |
226 char *p; 227 double a; |
|
212 | 228 |
213 while ((c = getopt(argc, argv, "I:d?")) != -1) { | 229 c = strlen(argv[0]); 230 if (argv[0][c - 1] == 'd') 231 is_daemon = 1; 232 while ((c = getopt(argc, argv, 233 is_daemon ? "I:de:s:t:?" : "dt:?")) != -1) { |
214 switch (c) { 215 case 'I': 216 pidfile = optarg; 217 break; 218 case 'd': 219 debugging = 1; 220 break; | 234 switch (c) { 235 case 'I': 236 pidfile = optarg; 237 break; 238 case 'd': 239 debugging = 1; 240 break; |
241 case 'e': 242 test_cmd = strdup(optarg); 243 break; 244#ifdef notyet 245 case 'p': 246 passive = 1; 247 break; 248#endif 249 case 's': 250 p = NULL; 251 errno = 0; 252 nap = strtol(optarg, &p, 0); 253 if ((p != NULL && *p != '\0') || errno != 0) 254 errx(EX_USAGE, "-s argument is not a number"); 255 break; 256 case 't': 257 p = NULL; 258 errno = 0; 259 a = strtod(optarg, &p); 260 if ((p != NULL && *p != '\0') || errno != 0) 261 errx(EX_USAGE, "-t argument is not a number"); 262 if (a < 0) 263 errx(EX_USAGE, "-t argument must be positive"); 264 if (a == 0) 265 timeout = WD_TO_NEVER; 266 else 267 timeout = 1.0 + log(a * 1e9) / log(2.0); 268 if (debugging) 269 printf("Timeout is 2^%d nanoseconds\n", 270 timeout); 271 break; |
|
221 case '?': 222 default: 223 usage(); 224 /* NOTREACHED */ 225 } 226 } | 272 case '?': 273 default: 274 usage(); 275 /* NOTREACHED */ 276 } 277 } |
278 if (is_daemon && timeout < WD_TO_1SEC) 279 errx(EX_USAGE, "-t argument is less than one second."); |
|
227} | 280} |