Subject: kill(1) a pid after timeout
To: None <tech-userlevel@netbsd.org>
From: Jan Schaumann <jschauma@netmeister.org>
List: tech-userlevel
Date: 07/24/2007 10:47:46
--ghzN8eJ9Qlbqn3iT
Content-Type: multipart/mixed; boundary="oC1+HKm2/end4ao3"
Content-Disposition: inline


--oC1+HKm2/end4ao3
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
Content-Transfer-Encoding: quoted-printable

Hi,

I occasionally have the need to kill a process iff it has been running
for longer than N seconds.  Instead of parsing the output of ps(1) and
then calling kill(1) myself, I have attached a patch to add the "-t
timeout" flag to kill(1).

Does that seem useful to others as well?

-Jan

--=20
Defending Freedom in the Digital World:
   --- Electronic Frontier Foundation -- http://www.eff.org ---

--oC1+HKm2/end4ao3
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename=diff
Content-Transfer-Encoding: quoted-printable

Index: Makefile
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /cvsroot/src/bin/kill/Makefile,v
retrieving revision 1.8
diff -b -u -r1.8 Makefile
--- Makefile	20 Jul 1997 22:37:09 -0000	1.8
+++ Makefile	21 Jul 2007 18:23:01 -0000
@@ -2,5 +2,7 @@
 #	@(#)Makefile	8.1 (Berkeley) 5/31/93
=20
 PROG=3D	kill
+DPADD=3D	${LIBKVM}
+LDADD=3D	-lkvm
=20
 .include <bsd.prog.mk>
Index: kill.1
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /cvsroot/src/bin/kill/kill.1,v
retrieving revision 1.18
diff -b -u -r1.18 kill.1
--- kill.1	7 Aug 2003 09:05:13 -0000	1.18
+++ kill.1	21 Jul 2007 18:23:01 -0000
@@ -41,6 +41,7 @@
 .Sh SYNOPSIS
 .Nm
 .Op Fl s Ar signal_name
+.Op Fl t Ar timeout
 .Ar pid
 \&...
 .Nm
@@ -48,10 +49,12 @@
 .Op Ar signal_number
 .Nm
 .Fl signal_name
+.Op Fl t Ar timeout
 .Ar pid
 \&...
 .Nm
 .Fl signal_number
+.Op Fl t Ar timeout
 .Ar pid
 \&...
 .Sh DESCRIPTION
@@ -69,6 +72,10 @@
 A symbolic signal name specifying the signal to be sent instead of the
 default
 .Dv TERM .
+.It Fl t Ar timeout
+Only kill the given process(es) if they have been running for longer than
+Ar timeout
+seconds.
 .It Fl l Op Ar signal_number
 If no operand is given, list the signal names; otherwise, write
 the signal name corresponding to
Index: kill.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /cvsroot/src/bin/kill/kill.c,v
retrieving revision 1.24
diff -b -u -r1.24 kill.c
--- kill.c	17 Mar 2006 22:30:11 -0000	1.24
+++ kill.c	21 Jul 2007 18:23:01 -0000
@@ -46,6 +46,8 @@
 #include <ctype.h>
 #include <err.h>
 #include <errno.h>
+#include <kvm.h>
+#include <limits.h>
 #include <signal.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -53,7 +55,9 @@
 #include <termios.h>
 #include <unistd.h>
 #include <locale.h>
+#include <sys/param.h>
 #include <sys/ioctl.h>
+#include <sys/sysctl.h>
=20
 #ifdef SHELL            /* sh (aka ash) builtin */
 #define main killcmd
@@ -69,8 +73,9 @@
 int
 main(int argc, char *argv[])
 {
-	int errors, numsig, pid;
+	int errors, numsig, pid, timeout;
 	char *ep;
+	kvm_t *kd;
=20
 	setprogname(argv[0]);
 	setlocale(LC_ALL, "");
@@ -78,6 +83,8 @@
 		usage();
=20
 	numsig =3D SIGTERM;
+	timeout =3D 0;
+	kd =3D NULL;
=20
 	argc--, argv++;
 	if (strcmp(*argv, "-l") =3D=3D 0) {
@@ -104,6 +111,21 @@
 		exit(0);
 	}
=20
+	if (!strcmp(*argv, "-t")) {
+		argc--, argv++;
+		if (argc < 1) {
+			warnx("option requires an argument -- t");
+			usage();
+		}
+		timeout =3D strtol(*argv, &ep, 10);
+		if (*ep) {
+			errx(EXIT_FAILURE, "illegal signal number: %s",
+				*argv);
+			/* NOTREACHED */
+		}
+		argc--, argv++;
+	}
+
 	if (!strcmp(*argv, "-s")) {
 		argc--, argv++;
 		if (argc < 1) {
@@ -138,7 +160,16 @@
 	if (argc =3D=3D 0)
 		usage();
=20
+	if (timeout) {
+		char errbuf[_POSIX2_LINE_MAX];
+		kd =3D kvm_openfiles(NULL, NULL, NULL, KVM_NO_FILES, errbuf);
+		if (kd =3D=3D 0)
+			errx(1, "%s", errbuf);
+			/* NOTREACHED */
+	}
+
 	for (errors =3D 0; argc; argc--, argv++) {
+		int do_kill =3D 1;
 #ifdef SHELL
 		extern int getjobpgrp(const char *);
 		if (*argv[0] =3D=3D '%') {
@@ -158,10 +189,29 @@
 				continue;
 			}
 		}
+
+		if (timeout) {
+			struct kinfo_proc2 *kinfo;
+			int nentries;
+
+			do_kill =3D 0;
+
+			if (!(kinfo =3D kvm_getproc2(kd, KERN_PROC_PID, pid,
+					sizeof(struct kinfo_proc2), &nentries)))
+				err(1, "%s", kvm_geterr(kd));
+				/* NOTREACHED */
+
+			if (kinfo->p_ustart_sec < (time(NULL) - timeout)) {
+				do_kill =3D 1;
+			}
+		}
+
+		if (do_kill) {
 		if (kill(pid, numsig) =3D=3D -1) {
 			warn("%s", *argv);
 			errors =3D 1;
 		}
+		}
 #ifdef SHELL
 		/* Wakeup the process if it was suspended, so it can
 		   exit without an explicit 'fg'. */
@@ -233,10 +283,10 @@
 usage(void)
 {
=20
-	fprintf(stderr, "usage: %s [-s signal_name] pid ...\n"
+	fprintf(stderr, "usage: %s [-s signal_name] [-t timeout] pid ...\n"
 	    "       %s -l [exit_status]\n"
-	    "       %s -signal_name pid ...\n"
-	    "       %s -signal_number pid ...\n",
+	    "       %s -signal_name [-t timeout] pid ...\n"
+	    "       %s -signal_number [-t timeout] pid ...\n",
 	    getprogname(), getprogname(), getprogname(), getprogname());
 	exit(1);
 	/* NOTREACHED */

--oC1+HKm2/end4ao3--

--ghzN8eJ9Qlbqn3iT
Content-Type: application/pgp-signature
Content-Disposition: inline

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.7 (NetBSD)

iD8DBQFGpjtCfFtkr68iakwRAhrPAKDpbnOrdBlFsnR+zGFh+j1LI1spLwCgo2+e
bdAzPuCGPZ0hXJYU9so8gO0=
=Tt+f
-----END PGP SIGNATURE-----

--ghzN8eJ9Qlbqn3iT--