Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 10 Jul 2001 00:27:37 -0700
From:      Dima Dorfman <dima@unixfreak.org>
To:        hackers@freebsd.org
Subject:   DDB 'kill' command
Message-ID:  <20010710072737.4AF893E28@bazooka.unixfreak.org>

next in thread | raw e-mail | index | archive | help
Hi folks,

The attached patch implements a 'kill' command in DDB.  Previously, it
was possible to do `call psignal(xxx,yyy)` and have it DTRT.  (This
was very useful when you accidently got your system so deep in the
hole that spawning kill(1) takes forever and even then possibly
doesn't succeed.)  However, psignal() doesn't respect locking by
itself, so trying that now leads to all kinds of badness.  This patch
basically wraps the psignal() call in a 'kill' command that respects
all necessary locks.

Actually, it isn't very clear exactly which locks it should respect.
The debugger is a special case in this way.  This patch uses the
PROC_TRYLOCK macro; if it fails, the command bails out.  Thus, it
can't use pfind()--the latter automatically does a PROC_LOCK--so it
has to walk the allproc list manually.  It does *not* attempt to get a
shared lock on the allproc list.  There is similar code in db_trace.c,
and it doesn't call sx_slock(), either; I asked jhb about this a while
ago, and all he said was that it is intentional.

Comments?  Suggestions?

Thanks,

					Dima Dorfman
					dima@unixfreak.org


Index: db_command.c
===================================================================
RCS file: /stl/src/FreeBSD/src/sys/ddb/db_command.c,v
retrieving revision 1.36
diff -u -r1.36 db_command.c
--- db_command.c	2001/07/08 04:56:05	1.36
+++ db_command.c	2001/07/10 07:19:45
@@ -36,7 +36,12 @@
  */
 #include <sys/param.h>
 #include <sys/linker_set.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/sx.h>
+#include <sys/proc.h>
 #include <sys/reboot.h>
+#include <sys/signalvar.h>
 #include <sys/systm.h>
 #include <sys/cons.h>
 
@@ -62,6 +67,7 @@
 
 static db_cmdfcn_t	db_fncall;
 static db_cmdfcn_t	db_gdb;
+static db_cmdfcn_t	db_kill;
 
 /* XXX this is actually forward-static. */
 extern struct command	db_show_cmds[];
@@ -413,6 +419,7 @@
 	{ "show",	0,			0,	db_show_cmds },
 	{ "ps",		db_ps,			0,	0 },
 	{ "gdb",	db_gdb,			0,	0 },
+	{ "kill",	db_kill,		CS_OWN,	0 },
 	{ (char *)0, }
 };
 
@@ -566,4 +573,44 @@
 	db_printf("Next trap will enter %s\n",
 		   boothowto & RB_GDB ? "GDB remote protocol mode"
 				      : "DDB debugger");
+}
+
+static void
+db_kill(dummy1, dummy2, dummy3, dummy4)
+	db_expr_t	dummy1;
+	boolean_t	dummy2;
+	db_expr_t	dummy3;
+	char *		dummy4;
+{
+	struct proc *p;
+	db_expr_t pid, sig;
+
+#define DB_ERROR(f)	do { db_printf f; db_flush_lex(); return; } while (0)
+
+	/* Retrieve arguments. */
+	if (!db_expression(&sig))
+		DB_ERROR(("Missing signal number\n"));
+	if (!db_expression(&pid))
+		DB_ERROR(("Missing process ID\n"));
+	db_skip_to_eol();
+	if (sig < 0 || sig > _SIG_MAXSIG)
+		DB_ERROR(("Signal number out of range\n"));
+
+	/* Find the process in queston. */
+	/* sx_slock(&allproc_lock); */
+	LIST_FOREACH(p, &allproc, p_list)
+	    if (p->p_pid == pid)
+		    break;
+	/* sx_sunlock(&allproc_lock); */
+	if (p == NULL)
+		DB_ERROR(("Can't find process with pid %d\n", pid));
+
+	/* If it's already locked, bail; otherwise, do the deed. */
+	if (PROC_TRYLOCK(p) == 0)
+		DB_ERROR(("Can't lock process with pid %d\n", pid));
+	else {
+		psignal(p, sig);
+		PROC_UNLOCK(p);
+	}
+#undef DB_ERROR
 }

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-hackers" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20010710072737.4AF893E28>