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}