Subject: rfc: an alternate user-tickle mode for wdogctl(8)
To: None <tech-userlevel@netbsd.org>
From: David Young <dyoung@pobox.com>
List: tech-userlevel
Date: 08/06/2006 14:18:11
--d6Gm4EdcadzBjdND
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

I have added a flag to wdogctl(8), -x, that activates a user-mode timer
that is NOT disarmed when wdogctl closes the watchdog device.  See the
attached patch.  The -x mode protects against the case where the kernel
kills wdogctl, sshd, and other essential userland programs are killed
due to, say, memory exhaustion, lobotomizing a mission-critical NetBSD
system and necessitating an operator visit to reboot it.  If there are
no objections, I will commit this on Wednesday.

Dave

-- 
David Young             OJC Technologies
dyoung@ojctech.com      Urbana, IL * (217) 278-3933

--d6Gm4EdcadzBjdND
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="wdogctl.patch"

Index: sbin/wdogctl/wdogctl.8
===================================================================
RCS file: /cvsroot/src/sbin/wdogctl/wdogctl.8,v
retrieving revision 1.12
diff -u -p -u -p -r1.12 wdogctl.8
--- sbin/wdogctl/wdogctl.8	21 Jan 2005 10:40:01 -0000	1.12
+++ sbin/wdogctl/wdogctl.8	6 Aug 2006 18:49:25 -0000
@@ -58,6 +58,11 @@
 .Op Fl A
 .Op Fl p Ar seconds
 .Ar timer
+.Nm
+.Fl x
+.Op Fl A
+.Op Fl p Ar seconds
+.Ar timer
 .Sh DESCRIPTION
 .Nm
 is used to manipulate watchdog timers.
@@ -87,7 +92,10 @@ Note that user tickle mode must be used 
 on a heavily loaded system, the timer may
 expire accidentally, even though user programs may be making
 (very slow) progress.
-A user-mode timer is disarmed (if possible) when the device is closed.
+A user-mode timer is disarmed (if possible) when the device is closed,
+unless the timer is activated with the
+.Fl x
+option.
 .Pp
 External-mode watchdogs are similar to user-mode watchdogs, except
 that the tickle must be done explicitly by a separate invocation of
@@ -144,6 +152,11 @@ This flag tickles an external mode timer
 Arm
 .Ar timer
 in user tickle mode.
+.It Fl x
+Arm
+.Ar timer
+in a modified user tickle mode: closing the device will not disarm
+the timer.
 .El
 .Sh FILES
 .Pa /dev/watchdog
Index: sbin/wdogctl/wdogctl.c
===================================================================
RCS file: /cvsroot/src/sbin/wdogctl/wdogctl.c,v
retrieving revision 1.15
diff -u -p -u -p -r1.15 wdogctl.c
--- sbin/wdogctl/wdogctl.c	31 Aug 2005 18:28:58 -0000	1.15
+++ sbin/wdogctl/wdogctl.c	6 Aug 2006 18:49:25 -0000
@@ -58,7 +58,7 @@ __RCSID("$NetBSD: wdogctl.c,v 1.15 2005/
 
 int	main(int, char *[]);
 void	enable_kernel(const char *, u_int);
-void	enable_user(const char *, u_int);
+void	enable_user(const char *, u_int, int);
 void	enable_ext(const char *, u_int);
 void	tickle_ext(void);
 void	disable(void);
@@ -75,6 +75,7 @@ enum	cmd {
 	CMD_DOTICKLE,
 	CMD_EXT_TICKLE,
 	CMD_KERN_TICKLE,
+	CMD_NOCANCEL_TICKLE,
 	CMD_USER_TICKLE
 };
 
@@ -86,7 +87,7 @@ main(int argc, char *argv[])
 	int ch;
 	u_int period = WDOG_PERIOD_DEFAULT;
 
-	while ((ch = getopt(argc, argv, "Adekp:ut")) != -1) {
+	while ((ch = getopt(argc, argv, "Adekp:utx")) != -1) {
 		switch (ch) {
 		case 'A':
 			Aflag = 1;
@@ -123,10 +124,12 @@ main(int argc, char *argv[])
 				usage();
 			break;
 
+		case 'x':
 		case 'u':
 			if (command != CMD_NONE)
 				usage();
-			command = CMD_USER_TICKLE;
+			command =
+			    (ch == 'u') ? CMD_USER_TICKLE : CMD_NOCANCEL_TICKLE;
 			break;
 
 		default:
@@ -161,8 +164,9 @@ main(int argc, char *argv[])
 	case CMD_KERN_TICKLE:
 		enable_kernel(argv[0], period);
 		break;
+	case CMD_NOCANCEL_TICKLE:
 	case CMD_USER_TICKLE:
-		enable_user(argv[0], period);
+		enable_user(argv[0], period, command == CMD_USER_TICKLE);
 		break;
 	}
 	exit(EXIT_SUCCESS);
@@ -218,14 +222,16 @@ enable_ext(const char *name, u_int perio
 }
 
 void
-enable_user(const char *name, u_int period)
+enable_user(const char *name, u_int period, int cancel_on_close)
 {
 	struct wdog_mode wm;  
 	struct timespec ts;
 	pid_t tickler;
 	int fd, rv;
 
-	prep_wmode(&wm, WDOG_MODE_UTICKLE, name, period);
+	prep_wmode(&wm,
+	    (cancel_on_close) ? WDOG_MODE_UTICKLE : WDOG_MODE_ETICKLE, name,
+	    period);
 
 	fd = open(_PATH_WATCHDOG, O_RDWR, 0644);
 	if (fd == -1)

--d6Gm4EdcadzBjdND--