Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 5 Oct 2002 00:20:22 -0700
From:      Juli Mallett <jmallett@FreeBSD.org>
To:        arch@FreeBSD.org
Subject:   [jmallett@FreeBSD.org: [PATCH] Reliable signal queues, etc., [for review]]
Message-ID:  <20021005002021.A14635@FreeBSD.org>

next in thread | raw e-mail | index | archive | help
Patch description:
Make the kernel use reliable signal queues, of a type which provides
information on the source of the signal source, sufficient to provide
RTS siginfo_t exporting.  Signal senders now operate using these info
structures, structs called 'ksiginfo', which have been dequeued before
being sent.  The p_sig and p_code fields have gone away, though their
use could *possibly* be replaced by taking the head of the signal queue,
in the case of dumping core files, though I am not entirely sure.  To
accomodate situations where allocation of a 'ksiginfo' is a failure
mode (no memory), the destination process is told to exit via a new
member of 'struct proc', p_suicide, which tells a process to kill itself
next time it goes through userret.  It is done this way to prevent a
recursive failure case, and to prevent possibly dying with extraneous
locks held, as signals are sent from odd places of the kernel.

Only i386-related machdep changes are included for the signal senders,
but the changes are small enough that I will make them before commit.

Testing:
Tested on i386 only, but the changes are mostly MI or exact between
architectures.  I have run this on both my desktop/laptop and on our
house fileserver.  In the process of stressing signals and edge cases,
I've actually managed to run into a few other bugs, but none in this
code.  I've run a ton of native binaries, including things like GNOME2
and X11.  I've also run a good deal of Linux binaries, such as xski,
simnow, etc.  Also some binary-only FreeBSD applications like p4 and p4d.

So far I have yet to run into a kernel or user-space failure case that I
have not addressed.

Imprvements over what was committed:
Various sundry, including some style changes to the subr_sigq.c and
ksiginfo.h files from bde.  The most notable change is that the most
recently sent && lowest numbered signal is sent, in the normal course
of events, rather than simply the lowest numbered or most recently
sent.  This [seems to] satisfy the RTS rules about which signals are
delivered first, at least as explained by Garrett Wollman.  I have not
implemented any KSE-related or userland RTS-related features, though
this should *ehlp* both things, and I'm willing to do such.

%%%
diff -Nrdu -x *CVS* -x *dev* sys/alpha/osf1/osf1_signal.c kernel/alpha/osf1/osf1_signal.c
--- sys/alpha/osf1/osf1_signal.c	Tue Oct  1 12:15:46 2002
+++ kernel/alpha/osf1/osf1_signal.c	Sat Oct  5 01:18:21 2002
@@ -30,7 +30,7 @@
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
- * $FreeBSD: src/sys/alpha/osf1/osf1_signal.c,v 1.22 2002/10/01 17:15:46 jmallett Exp $
+ * $FreeBSD: src/sys/alpha/osf1/osf1_signal.c,v 1.21 2002/10/01 00:07:25 jmallett Exp $
  */
 
 #include <sys/param.h>
@@ -46,6 +46,7 @@
 #include <sys/buf.h>
 #include <sys/bus.h>
 #include <sys/mbuf.h>
+#include <sys/ksiginfo.h>
 #include <sys/vmmeter.h>
 #include <sys/msgbuf.h>
 #include <sys/exec.h>
@@ -523,7 +524,7 @@
 
 	p = td->td_proc;
 	PROC_LOCK(p);
-	bss = p->p_siglist;
+	ksiginfo_to_sigset_t(p, &bss);
 	SIGSETAND(bss, p->p_sigmask);
 	PROC_UNLOCK(p);
 	bsd_to_osf1_sigset(&bss, &oss);
diff -Nrdu -x *CVS* -x *dev* sys/compat/linprocfs/linprocfs.c kernel/compat/linprocfs/linprocfs.c
--- sys/compat/linprocfs/linprocfs.c	Tue Oct  1 12:15:49 2002
+++ kernel/compat/linprocfs/linprocfs.c	Sat Oct  5 01:18:43 2002
@@ -38,7 +38,7 @@
  *
  *	@(#)procfs_status.c	8.4 (Berkeley) 6/15/94
  *
- * $FreeBSD: src/sys/compat/linprocfs/linprocfs.c,v 1.58 2002/10/01 17:15:49 jmallett Exp $
+ * $FreeBSD: src/sys/compat/linprocfs/linprocfs.c,v 1.57 2002/10/01 00:07:25 jmallett Exp $
  */
 
 #include <sys/param.h>
@@ -651,7 +651,7 @@
 	 * running on anything but i386, so ignore that for now.
 	 */
 	PROC_LOCK(p);
-	sbuf_printf(sb, "SigPnd:\t%08x\n",	p->p_siglist.__bits[0]);
+	sbuf_printf(sb, "SigPnd:\t%08x\n",	0); /* XXX */
 	/*
 	 * I can't seem to find out where the signal mask is in
 	 * relation to struct proc, so SigBlk is left unimplemented.
diff -Nrdu -x *CVS* -x *dev* sys/compat/linux/linux_misc.c kernel/compat/linux/linux_misc.c
--- sys/compat/linux/linux_misc.c	Tue Oct  1 12:15:50 2002
+++ kernel/compat/linux/linux_misc.c	Sat Oct  5 01:18:44 2002
@@ -25,7 +25,7 @@
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
- * $FreeBSD: src/sys/compat/linux/linux_misc.c,v 1.133 2002/10/01 17:15:50 jmallett Exp $
+ * $FreeBSD: src/sys/compat/linux/linux_misc.c,v 1.132 2002/10/01 00:07:25 jmallett Exp $
  */
 
 #include "opt_mac.h"
@@ -36,6 +36,7 @@
 #include <sys/imgact_aout.h>
 #include <sys/jail.h>
 #include <sys/kernel.h>
+#include <sys/ksiginfo.h>
 #include <sys/lock.h>
 #include <sys/mac.h>
 #include <sys/malloc.h>
@@ -806,6 +807,7 @@
 int
 linux_wait4(struct thread *td, struct linux_wait4_args *args)
 {
+	struct proc *p;
 	struct wait_args /* {
 		int pid;
 		int *status;
@@ -821,6 +823,8 @@
 		    (void *)args->rusage);
 #endif
 
+	p = td->td_proc;
+
 	tmp.pid = args->pid;
 	tmp.status = args->status;
 	tmp.options = (args->options & (WNOHANG | WUNTRACED));
@@ -832,7 +836,9 @@
 	if ((error = wait4(td, &tmp)) != 0)
 		return error;
 
-	SIGDELSET(td->td_proc->p_siglist, SIGCHLD);
+	PROC_LOCK(p);
+	signal_delete(p, NULL, SIGCHLD);
+	PROC_UNLOCK(p);
 
 	if (args->status) {
 		if ((error = copyin((caddr_t)args->status, &tmpstat,
diff -Nrdu -x *CVS* -x *dev* sys/compat/linux/linux_signal.c kernel/compat/linux/linux_signal.c
--- sys/compat/linux/linux_signal.c	Tue Oct  1 12:15:50 2002
+++ kernel/compat/linux/linux_signal.c	Sat Oct  5 01:18:44 2002
@@ -25,7 +25,7 @@
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
- * $FreeBSD: src/sys/compat/linux/linux_signal.c,v 1.38 2002/10/01 17:15:50 jmallett Exp $
+ * $FreeBSD: src/sys/compat/linux/linux_signal.c,v 1.37 2002/10/01 00:07:25 jmallett Exp $
  */
 
 #include <sys/param.h>
@@ -34,6 +34,7 @@
 #include <sys/mutex.h>
 #include <sys/proc.h>
 #include <sys/signalvar.h>
+#include <sys/ksiginfo.h>
 #include <sys/syscallsubr.h>
 #include <sys/sysproto.h>
 
@@ -390,7 +391,7 @@
 #endif
 
 	PROC_LOCK(p);
-	bset = p->p_siglist;
+	ksiginfo_to_sigset_t(p, &bset);
 	SIGSETAND(bset, p->p_sigmask);
 	bsd_to_linux_sigset(&bset, &lset);
 	PROC_UNLOCK(p);
diff -Nrdu -x *CVS* -x *dev* sys/compat/svr4/svr4_filio.c kernel/compat/svr4/svr4_filio.c
--- sys/compat/svr4/svr4_filio.c	Tue Oct  1 12:15:50 2002
+++ kernel/compat/svr4/svr4_filio.c	Sat Oct  5 01:18:45 2002
@@ -25,7 +25,7 @@
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  * 
- * $FreeBSD: src/sys/compat/svr4/svr4_filio.c,v 1.19 2002/10/01 17:15:50 jmallett Exp $
+ * $FreeBSD: src/sys/compat/svr4/svr4_filio.c,v 1.18 2002/10/01 00:07:26 jmallett Exp $
  */
 
 #include <sys/param.h>
@@ -39,6 +39,7 @@
 #include <sys/poll.h>
 #include <sys/malloc.h>
 #include <sys/mutex.h>
+#include <sys/ksiginfo.h>
 
 #include <sys/sysproto.h>
 
@@ -135,7 +136,9 @@
        DPRINTF(("sigmask = 0x%x\n", td->td_proc->p_sigmask));
        DPRINTF(("sigignore = 0x%x\n", td->td_proc->p_sigignore));
        DPRINTF(("sigcaught = 0x%x\n", td->td_proc->p_sigcatch));
+#if 0 /* XXX - use ksiginfo_to_sigset_t ? */
        DPRINTF(("siglist = 0x%x\n", td->td_proc->p_siglist));
+#endif
      }
 
 #if defined(GROTTY_READ_HACK)
diff -Nrdu -x *CVS* -x *dev* sys/compat/svr4/svr4_signal.c kernel/compat/svr4/svr4_signal.c
--- sys/compat/svr4/svr4_signal.c	Tue Oct  1 12:15:50 2002
+++ kernel/compat/svr4/svr4_signal.c	Sat Oct  5 01:18:46 2002
@@ -25,7 +25,7 @@
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  * 
- * $FreeBSD: src/sys/compat/svr4/svr4_signal.c,v 1.21 2002/10/01 17:15:50 jmallett Exp $
+ * $FreeBSD: src/sys/compat/svr4/svr4_signal.c,v 1.20 2002/10/01 00:07:26 jmallett Exp $
  */
 
 #include <sys/param.h>
@@ -565,7 +565,7 @@
 		if (SCARG(uap, mask) == NULL)
 			return 0;
 		PROC_LOCK(td->td_proc);
-		bss = td->td_proc->p_siglist;
+		ksiginfo_to_sigset_t(td->td_proc, &bss);
 		SIGSETAND(bss, td->td_proc->p_sigmask);
 		PROC_UNLOCK(td->td_proc);
 		bsd_to_svr4_sigset(&bss, &sss);
diff -Nrdu -x *CVS* -x *dev* sys/fs/procfs/procfs_ctl.c kernel/fs/procfs/procfs_ctl.c
--- sys/fs/procfs/procfs_ctl.c	Tue Oct  1 12:15:51 2002
+++ kernel/fs/procfs/procfs_ctl.c	Sat Oct  5 01:20:20 2002
@@ -38,7 +38,7 @@
  *
  * From:
  *	$Id: procfs_ctl.c,v 3.2 1993/12/15 09:40:17 jsp Exp $
- * $FreeBSD: src/sys/fs/procfs/procfs_ctl.c,v 1.47 2002/10/01 17:15:51 jmallett Exp $
+ * $FreeBSD: src/sys/fs/procfs/procfs_ctl.c,v 1.46 2002/10/01 00:07:26 jmallett Exp $
  */
 
 #include <sys/param.h>
@@ -51,6 +51,7 @@
 #include <sys/signalvar.h>
 #include <sys/sx.h>
 #include <sys/uio.h>
+#include <sys/ksiginfo.h>
 
 #include <fs/pseudofs/pseudofs.h>
 #include <fs/procfs/procfs.h>
@@ -221,7 +222,7 @@
 		p->p_flag &= ~P_TRACED;
 
 		/* remove pending SIGTRAP, else the process will die */
-		SIGDELSET(p->p_siglist, SIGTRAP);
+		signal_delete(p, NULL, SIGTRAP);
 		PROC_UNLOCK(p);
 
 		/* give process back to original parent */
diff -Nrdu -x *CVS* -x *dev* sys/i386/i386/machdep.c kernel/i386/i386/machdep.c
--- sys/i386/i386/machdep.c	Mon Sep 30 02:02:22 2002
+++ kernel/i386/i386/machdep.c	Sat Oct  5 01:20:27 2002
@@ -1,4 +1,6 @@
 /*-
+ * Copyright (c) 2002 Juli Mallett.
+ * Copyright (c) 2002 New Gold Technology.
  * Copyright (c) 1992 Terrence R. Lambert.
  * Copyright (c) 1982, 1987, 1990 The Regents of the University of California.
  * All rights reserved.
@@ -75,6 +77,7 @@
 #include <sys/vmmeter.h>
 #include <sys/bus.h>
 #include <sys/eventhandler.h>
+#include <sys/ksiginfo.h>
 
 #include <vm/vm.h>
 #include <vm/vm_param.h>
@@ -408,11 +411,7 @@
 #endif /* COMPAT_43 */
 
 void
-sendsig(catcher, sig, mask, code)
-	sig_t catcher;
-	int sig;
-	sigset_t *mask;
-	u_long code;
+sendsig(sig_t catcher, struct ksiginfo *ksi, sigset_t *mask)
 {
 	struct sigframe sf;
 	struct proc *p;
@@ -420,15 +419,16 @@
 	struct sigacts *psp;
 	struct trapframe *regs;
 	struct sigframe *sfp;
-	int oonstack;
+	int oonstack, sig;
 
+	sig = ksi->ksi_signo;
 	td = curthread;
 	p = td->td_proc;
 	PROC_LOCK_ASSERT(p, MA_OWNED);
 	psp = p->p_sigacts;
 #ifdef COMPAT_43
 	if (SIGISMEMBER(psp->ps_osigset, sig)) {
-		osendsig(catcher, sig, mask, code);
+		osendsig(catcher, sig, mask, ksi->ksi_code);
 		return;
 	}
 #endif
@@ -473,15 +473,11 @@
 		sf.sf_siginfo = (register_t)&sfp->sf_si;
 		sf.sf_ahu.sf_action = (__siginfohandler_t *)catcher;
 
-		/* Fill in POSIX parts */
-		sf.sf_si.si_signo = sig;
-		sf.sf_si.si_code = code;
+		ksiginfo_to_siginfo_t(ksi, &sf.sf_si);
 		sf.sf_si.si_addr = (void *)regs->tf_err;
-		sf.sf_si.si_pid = p->p_pid;
-		sf.sf_si.si_uid = p->p_ucred->cr_uid;
 	} else {
 		/* Old FreeBSD-style arguments. */
-		sf.sf_siginfo = code;
+		sf.sf_siginfo = ksi->ksi_code;
 		sf.sf_addr = regs->tf_err;
 		sf.sf_ahu.sf_handler = catcher;
 	}
diff -Nrdu -x *CVS* -x *dev* sys/i386/ibcs2/ibcs2_signal.c kernel/i386/ibcs2/ibcs2_signal.c
--- sys/i386/ibcs2/ibcs2_signal.c	Tue Oct  1 12:15:51 2002
+++ kernel/i386/ibcs2/ibcs2_signal.c	Sat Oct  5 01:20:29 2002
@@ -25,12 +25,13 @@
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
- * $FreeBSD: src/sys/i386/ibcs2/ibcs2_signal.c,v 1.25 2002/10/01 17:15:51 jmallett Exp $
+ * $FreeBSD: src/sys/i386/ibcs2/ibcs2_signal.c,v 1.22 2002/08/25 13:17:09 charnier Exp $
  */
 
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/lock.h>
+#include <sys/ksiginfo.h>
 #include <sys/mutex.h>
 #include <sys/signalvar.h>
 #include <sys/sysproto.h>
@@ -452,11 +453,11 @@
 	struct ibcs2_sigpending_args *uap;
 {
 	struct proc *p = td->td_proc;
-	sigset_t bss;
+	sigset_t curset;
 	ibcs2_sigset_t iss;
 
 	PROC_LOCK(p);
-	bss = p->p_siglist;
+	ksiginfo_to_sigset_t(p, &bss);
 	SIGSETAND(bss, p->p_sigmask);
 	PROC_UNLOCK(p);
 	bsd_to_ibcs2_sigset(&bss, &iss);
diff -Nrdu -x *CVS* -x *dev* sys/i386/linux/linux_sysvec.c kernel/i386/linux/linux_sysvec.c
--- sys/i386/linux/linux_sysvec.c	Sat Sep  7 17:31:44 2002
+++ kernel/i386/linux/linux_sysvec.c	Sat Oct  5 01:20:41 2002
@@ -40,6 +40,7 @@
 #include <sys/imgact.h>
 #include <sys/imgact_aout.h>
 #include <sys/imgact_elf.h>
+#include <sys/ksiginfo.h>
 #include <sys/lock.h>
 #include <sys/malloc.h>
 #include <sys/mutex.h>
@@ -108,8 +109,8 @@
 		    struct image_params *iparams);
 static void	linux_prepsyscall(struct trapframe *tf, int *args, u_int *code,
 		    caddr_t *params);
-static void     linux_sendsig(sig_t catcher, int sig, sigset_t *mask,
-		    u_long code);
+static void     linux_sendsig(sig_t catcher, struct ksiginfo *ksi,
+		    sigset_t *mask);
 
 /*
  * Linux syscalls return negative errno's, we do positive and map them
@@ -395,15 +396,18 @@
  */
 
 static void
-linux_sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code)
+linux_sendsig(sig_t catcher, struct ksiginfo *ksi, sigset_t *mask)
 {
 	register struct thread *td = curthread;
 	register struct proc *p = td->td_proc;
 	register struct trapframe *regs;
 	struct l_sigframe *fp, frame;
 	l_sigset_t lmask;
-	int oonstack, i;
+	int oonstack, i, sig;
+	u_long code;
 
+	sig = ksi->ksi_signo;
+	code = ksi->ksi_code;
 	PROC_LOCK_ASSERT(p, MA_OWNED);
 	if (SIGISMEMBER(p->p_sigacts->ps_siginfo, sig)) {
 		/* Signal handler installed with SA_SIGINFO. */
diff -Nrdu -x *CVS* -x *dev* sys/kern/imgact_elf.c kernel/kern/imgact_elf.c
--- sys/kern/imgact_elf.c	Sat Sep 21 17:07:16 2002
+++ kernel/kern/imgact_elf.c	Sat Oct  5 01:20:56 2002
@@ -1100,7 +1100,6 @@
 	status->pr_gregsetsz = sizeof(gregset_t);
 	status->pr_fpregsetsz = sizeof(fpregset_t);
 	status->pr_osreldate = osreldate;
-	status->pr_cursig = p->p_sig;
 	status->pr_pid = p->p_pid;
 	fill_regs(td, &status->pr_reg);
 
diff -Nrdu -x *CVS* -x *dev* sys/kern/init_main.c kernel/kern/init_main.c
--- sys/kern/init_main.c	Tue Oct  1 12:15:51 2002
+++ kernel/kern/init_main.c	Sat Oct  5 01:20:56 2002
@@ -39,7 +39,7 @@
  * SUCH DAMAGE.
  *
  *	@(#)init_main.c	8.9 (Berkeley) 1/21/94
- * $FreeBSD: src/sys/kern/init_main.c,v 1.210 2002/10/01 17:15:51 jmallett Exp $
+ * $FreeBSD: src/sys/kern/init_main.c,v 1.209 2002/10/01 00:07:26 jmallett Exp $
  */
 
 #include "opt_init_path.h"
@@ -347,6 +347,8 @@
 	LIST_INSERT_HEAD(PGRPHASH(0), &pgrp0, pg_hash);
 	LIST_INIT(&pgrp0.pg_members);
 	LIST_INSERT_HEAD(&pgrp0.pg_members, p, p_pglist);
+
+	TAILQ_INIT(&p->p_sigq);
 
 	pgrp0.pg_session = &session0;
 	mtx_init(&session0.s_mtx, "session", NULL, MTX_DEF);
diff -Nrdu -x *CVS* -x *dev* sys/kern/kern_exit.c kernel/kern/kern_exit.c
--- sys/kern/kern_exit.c	Tue Oct  1 12:15:51 2002
+++ kernel/kern/kern_exit.c	Sat Oct  5 01:20:57 2002
@@ -36,7 +36,7 @@
  * SUCH DAMAGE.
  *
  *	@(#)kern_exit.c	8.7 (Berkeley) 2/12/94
- * $FreeBSD: src/sys/kern/kern_exit.c,v 1.180 2002/10/01 17:15:51 jmallett Exp $
+ * $FreeBSD: src/sys/kern/kern_exit.c,v 1.179 2002/10/01 00:07:27 jmallett Exp $
  */
 
 #include "opt_compat.h"
@@ -67,6 +67,7 @@
 #ifdef KTRACE
 #include <sys/ktrace.h>
 #endif
+#include <sys/ksiginfo.h>
 
 #include <vm/vm.h>
 #include <vm/vm_extern.h>
@@ -209,12 +210,12 @@
 	PROC_LOCK(p);
 	if (p == p->p_leader) {
 		q = p->p_peers;
+		PROC_UNLOCK(p);
 		while (q != NULL) {
-			PROC_LOCK(q);
 			psignal(q, SIGKILL);
-			PROC_UNLOCK(q);
 			q = q->p_peers;
 		}
+		PROC_LOCK(p);
 		while (p->p_peers) 
 			msleep(p, &p->p_mtx, PWAIT, "exit1", 0);
 	}
@@ -244,7 +245,7 @@
 	 */
 	PROC_LOCK(p);
 	p->p_flag &= ~(P_TRACED | P_PPWAIT);
-	SIGEMPTYSET(p->p_siglist);
+	signal_delete(p, NULL, 0);
 	PROC_UNLOCK(p);
 	if (timevalisset(&p->p_realtimer.it_value))
 		callout_stop(&p->p_itcallout);
@@ -473,6 +474,12 @@
 	 */
 	if (p->p_flag & P_KTHREAD)
 		wakeup(p);
+
+	/*
+	 * And now, kill off its signals...
+	 */
+	signal_delete(p, NULL, 0);
+
 	PROC_UNLOCK(p);
 	
 	/*
diff -Nrdu -x *CVS* -x *dev* sys/kern/kern_fork.c kernel/kern/kern_fork.c
--- sys/kern/kern_fork.c	Tue Oct  1 12:15:51 2002
+++ kernel/kern/kern_fork.c	Sat Oct  5 01:20:57 2002
@@ -36,7 +36,7 @@
  * SUCH DAMAGE.
  *
  *	@(#)kern_fork.c	8.6 (Berkeley) 4/8/94
- * $FreeBSD: src/sys/kern/kern_fork.c,v 1.167 2002/10/01 17:15:51 jmallett Exp $
+ * $FreeBSD: src/sys/kern/kern_fork.c,v 1.166 2002/10/01 00:07:27 jmallett Exp $
  */
 
 #include "opt_ktrace.h"
@@ -605,6 +605,7 @@
 	LIST_INSERT_AFTER(p1, p2, p_pglist);
 	PGRP_UNLOCK(p1->p_pgrp);
 	LIST_INIT(&p2->p_children);
+	TAILQ_INIT(&p2->p_sigq);
 
 	callout_init(&p2->p_itcallout, 0);
 
diff -Nrdu -x *CVS* -x *dev* sys/kern/kern_kthread.c kernel/kern/kern_kthread.c
--- sys/kern/kern_kthread.c	Tue Oct  1 12:15:51 2002
+++ kernel/kern/kern_kthread.c	Sat Oct  5 01:20:57 2002
@@ -23,7 +23,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD: src/sys/kern/kern_kthread.c,v 1.27 2002/10/01 17:15:51 jmallett Exp $
+ * $FreeBSD: src/sys/kern/kern_kthread.c,v 1.26 2002/10/01 00:07:27 jmallett Exp $
  */
 
 #include <sys/param.h>
@@ -37,6 +37,7 @@
 #include <sys/sx.h>
 #include <sys/unistd.h>
 #include <sys/wait.h>
+#include <sys/ksiginfo.h>
 
 #include <machine/stdarg.h>
 
@@ -144,33 +145,29 @@
 {
 	/*
 	 * Make sure this is indeed a system process and we can safely
-	 * use the p_siglist field.
+	 * use the signal queue.
 	 */
 	PROC_LOCK(p);
 	if ((p->p_flag & P_KTHREAD) == 0) {
 		PROC_UNLOCK(p);
 		return (EINVAL);
 	}
-	SIGADDSET(p->p_siglist, SIGSTOP);
+	signal_add(p, NULL, SIGSTOP);
 	wakeup(p);
-	return msleep(&p->p_siglist, &p->p_mtx, PPAUSE | PDROP, "suspkt", timo);
+	return msleep(&p->p_sigq, &p->p_mtx, PPAUSE | PDROP, "suspkt", timo);
 }
 
 int
 kthread_resume(struct proc *p)
 {
-	/*
-	 * Make sure this is indeed a system process and we can safely
-	 * use the p_siglist field.
-	 */
 	PROC_LOCK(p);
 	if ((p->p_flag & P_KTHREAD) == 0) {
 		PROC_UNLOCK(p);
 		return (EINVAL);
 	}
-	SIGDELSET(p->p_siglist, SIGSTOP);
+	signal_delete(p, NULL, SIGSTOP);
 	PROC_UNLOCK(p);
-	wakeup(&p->p_siglist);
+	wakeup(&p->p_sigq);
 	return (0);
 }
 
@@ -178,9 +175,9 @@
 kthread_suspend_check(struct proc *p)
 {
 	PROC_LOCK(p);
-	while (SIGISMEMBER(p->p_siglist, SIGSTOP)) {
-		wakeup(&p->p_siglist);
-		msleep(&p->p_siglist, &p->p_mtx, PPAUSE, "ktsusp", 0);
+	while (signal_queued(p, SIGSTOP)) {
+		wakeup(&p->p_sigq);
+		msleep(&p->p_sigq, &p->p_mtx, PPAUSE, "ktsusp", 0);
 	}
 	PROC_UNLOCK(p);
 }
diff -Nrdu -x *CVS* -x *dev* sys/kern/kern_proc.c kernel/kern/kern_proc.c
--- sys/kern/kern_proc.c	Tue Oct  1 12:15:51 2002
+++ kernel/kern/kern_proc.c	Sat Oct  5 01:20:58 2002
@@ -31,7 +31,7 @@
  * SUCH DAMAGE.
  *
  *	@(#)kern_proc.c	8.7 (Berkeley) 2/14/95
- * $FreeBSD: src/sys/kern/kern_proc.c,v 1.157 2002/10/01 17:15:51 jmallett Exp $
+ * $FreeBSD: src/sys/kern/kern_proc.c,v 1.156 2002/10/01 00:07:27 jmallett Exp $
  */
 
 #include "opt_ktrace.h"
@@ -58,6 +58,7 @@
 #include <sys/uio.h>
 #include <sys/ktrace.h>
 #endif
+#include <sys/ksiginfo.h>
 
 #include <vm/vm.h>
 #include <vm/vm_extern.h>
@@ -408,7 +409,7 @@
 		      RANGEOF(struct kse, ke_startcopy, ke_endcopy));
 #endif
 		PROC_LOCK(p);
-		if (SIGPENDING(p))
+		if (signal_pending(p))
 			newke->ke_flags |= KEF_ASTPENDING;
 		PROC_UNLOCK(p);
 		mtx_lock_spin(&sched_lock);
@@ -1014,7 +1015,7 @@
 		strncpy(kp->ki_comm, p->p_comm, sizeof(kp->ki_comm) - 1);
 		strncpy(kp->ki_ocomm, p->p_comm, sizeof(kp->ki_ocomm) - 1);
 	}
-	kp->ki_siglist = p->p_siglist;
+	ksiginfo_to_sigset_t(p, &kp->ki_siglist);
 	kp->ki_sigmask = p->p_sigmask;
 	kp->ki_xstat = p->p_xstat;
 	kp->ki_acflag = p->p_acflag;
diff -Nrdu -x *CVS* -x *dev* sys/kern/kern_sig.c kernel/kern/kern_sig.c
--- sys/kern/kern_sig.c	Tue Oct  1 12:15:51 2002
+++ kernel/kern/kern_sig.c	Sat Oct  5 01:20:58 2002
@@ -1,4 +1,6 @@
 /*
+ * Copyright (c) 2002 New Gold Technoloy.  All rights reserved.
+ * Copyright (c) 2002 Juli Mallett.  All rights reserved.
  * Copyright (c) 1982, 1986, 1989, 1991, 1993
  *	The Regents of the University of California.  All rights reserved.
  * (c) UNIX System Laboratories, Inc.
@@ -36,7 +38,7 @@
  * SUCH DAMAGE.
  *
  *	@(#)kern_sig.c	8.7 (Berkeley) 4/18/94
- * $FreeBSD: src/sys/kern/kern_sig.c,v 1.195 2002/10/01 17:15:51 jmallett Exp $
+ * $FreeBSD: src/sys/kern/kern_sig.c,v 1.194 2002/10/01 00:16:16 jmallett Exp $
  */
 
 #include "opt_compat.h"
@@ -70,6 +72,7 @@
 #include <sys/sysctl.h>
 #include <sys/malloc.h>
 #include <sys/unistd.h>
+#include <sys/ksiginfo.h>
 
 #include <machine/cpu.h>
 
@@ -116,6 +119,9 @@
 SYSCTL_INT(_kern, OID_AUTO, coredump, CTLFLAG_RW,
 	&do_coredump, 0, "Enable/Disable coredumps");
 
+static int stopmask =
+    sigmask(SIGSTOP) | sigmask(SIGTSTP) | sigmask(SIGTTIN) | sigmask(SIGTTOU);
+
 /*
  * Signal properties and actions.
  * The array below categorizes the signals and their default actions
@@ -178,12 +184,12 @@
 
 	PROC_LOCK_ASSERT(p, MA_OWNED);
 	mtx_assert(&sched_lock, MA_NOTOWNED);
-	return (SIGPENDING(p) ? issignal(td) : 0);
+	return (signal_pending(p) ? issignal(td) : 0);
 }
 
 /*
  * Arrange for ast() to handle unmasked pending signals on return to user
- * mode.  This must be called whenever a signal is added to p_siglist or
+ * mode.  This must be called whenever a signal is added to p_sigq or
  * unmasked in p_sigmask.
  */
 void
@@ -194,7 +200,7 @@
 
 	PROC_LOCK_ASSERT(p, MA_OWNED);
 	mtx_lock_spin(&sched_lock);
-	if (SIGPENDING(p)) {
+	if (signal_pending(p)) {
 		p->p_sflag |= PS_NEEDSIGCHK;
 		/* XXXKSE for now punish all KSEs */
 		FOREACH_KSEGRP_IN_PROC(p, kg) {
@@ -341,7 +347,7 @@
 		    (sigprop(sig) & SA_IGNORE &&
 		     ps->ps_sigact[_SIG_IDX(sig)] == SIG_DFL)) {
 			/* never to be seen again */
-			SIGDELSET(p->p_siglist, sig);
+			signal_delete(p, NULL, sig);
 			if (sig != SIGCONT)
 				/* easier in psignal */
 				SIGADDSET(p->p_sigignore, sig);
@@ -494,7 +500,7 @@
 		if (sigprop(sig) & SA_IGNORE) {
 			if (sig != SIGCONT)
 				SIGADDSET(p->p_sigignore, sig);
-			SIGDELSET(p->p_siglist, sig);
+			signal_delete(p, NULL, sig);
 		}
 		ps->ps_sigact[_SIG_IDX(sig)] = SIG_DFL;
 	}
@@ -641,7 +647,7 @@
 
 	mtx_lock(&Giant);
 	PROC_LOCK(p);
-	siglist = p->p_siglist;
+	ksiginfo_to_sigset_t(p, &siglist);
 	PROC_UNLOCK(p);
 	mtx_unlock(&Giant);
 	error = copyout(&siglist, uap->set, sizeof(sigset_t));
@@ -664,10 +670,12 @@
 	struct osigpending_args *uap;
 {
 	struct proc *p = td->td_proc;
+	sigset_t siglist;
 
 	mtx_lock(&Giant);
 	PROC_LOCK(p);
-	SIG2OSIG(p->p_siglist, td->td_retval[0]);
+	ksiginfo_to_sigset_t(p, &siglist);
+	SIG2OSIG(siglist, td->td_retval[0]);
 	PROC_UNLOCK(p);
 	mtx_unlock(&Giant);
 	return (0);
@@ -1219,7 +1227,10 @@
 	u_long code;
 {
 	register struct sigacts *ps = p->p_sigacts;
+	struct ksiginfo *ksi;
 
+	ksiginfo_alloc(&ksi, p, sig);
+	ksi->ksi_code = code;
 	PROC_LOCK(p);
 	if ((p->p_flag & P_TRACED) == 0 && SIGISMEMBER(p->p_sigcatch, sig) &&
 	    !SIGISMEMBER(p->p_sigmask, sig)) {
@@ -1229,8 +1240,9 @@
 			ktrpsig(sig, ps->ps_sigact[_SIG_IDX(sig)],
 			    &p->p_sigmask, code);
 #endif
-		(*p->p_sysent->sv_sendsig)(ps->ps_sigact[_SIG_IDX(sig)], sig,
-						&p->p_sigmask, code);
+		(*p->p_sysent->sv_sendsig)(ps->ps_sigact[_SIG_IDX(sig)], ksi,
+						&p->p_sigmask);
+		ksiginfo_destroy(&ksi);
 		SIGSETOR(p->p_sigmask, ps->ps_catchmask[_SIG_IDX(sig)]);
 		if (!SIGISMEMBER(ps->ps_signodefer, sig))
 			SIGADDSET(p->p_sigmask, sig);
@@ -1244,11 +1256,8 @@
 				SIGADDSET(p->p_sigignore, sig);
 			ps->ps_sigact[_SIG_IDX(sig)] = SIG_DFL;
 		}
-	} else {
-		p->p_code = code;	/* XXX for core dump/debugger */
-		p->p_sig = sig;		/* XXX to verify code */
+	} else
 		psignal(p, sig);
-	}
 	PROC_UNLOCK(p);
 }
 
@@ -1308,7 +1317,7 @@
 	}
 
 	if (prop & SA_CONT)
-		SIG_STOPSIGMASK(p->p_siglist);
+		signal_delete_mask(p, stopmask);
 
 	if (prop & SA_STOP) {
 		/*
@@ -1321,10 +1330,10 @@
 		    (p->p_pgrp->pg_jobc == 0) &&
 		    (action == SIG_DFL))
 		        return;
-		SIG_CONTSIGMASK(p->p_siglist);
+		signal_delete_mask(p, sigmask(SIGCONT));
 		p->p_flag &= ~P_CONTINUED;
 	}
-	SIGADDSET(p->p_siglist, sig);
+	signal_add(p, NULL, sig);
 	signotify(p);			/* uses schedlock */
 
 	/*
@@ -1362,10 +1371,10 @@
 		if (prop & SA_CONT) {
 			/*
 			 * If SIGCONT is default (or ignored), we continue the
-			 * process but don't leave the signal in p_siglist as
-			 * it has no further action.  If SIGCONT is held, we
+			 * process but don't leave the signal in p_sigq as it
+			 * has no further action.  If SIGCONT is held, we
 			 * continue the process and leave the signal in
-			 * p_siglist.  If the process catches SIGCONT, let it
+			 * p_sigq.  If the process catches SIGCONT, let it
 			 * handle the signal itself.  If it isn't waiting on
 			 * an event, it goes back to run state.
 			 * Otherwise, process goes back to sleep state.
@@ -1373,7 +1382,7 @@
 			p->p_flag &= ~P_STOPPED_SIG;
 			p->p_flag |= P_CONTINUED;
 			if (action == SIG_DFL) {
-				SIGDELSET(p->p_siglist, sig);
+				signal_delete(p, NULL, sig);
 			} else if (action == SIG_CATCH) {
 				/*
 				 * The process wants to catch it so it needs
@@ -1403,7 +1412,7 @@
 			 * Just make sure the signal STOP bit set.
 			 */
 			p->p_flag |= P_STOPPED_SIG;
-			SIGDELSET(p->p_siglist, sig);
+			signal_delete(p, NULL, sig);
 			goto out;
 		}
 
@@ -1437,7 +1446,7 @@
 			/*
 			 * Already active, don't need to start again.
 			 */
-			SIGDELSET(p->p_siglist, sig);
+			signal_delete(p, NULL, sig);
 			goto out;
 		}
 		if ((p->p_flag & P_TRACED) || (action != SIG_DFL) ||
@@ -1461,7 +1470,7 @@
 				mtx_unlock_spin(&sched_lock);
 				stop(p);
 				p->p_xstat = sig;
-				SIGDELSET(p->p_siglist, sig);
+				signal_delete(p, NULL, sig);
 				PROC_LOCK(p->p_pptr);
 				if ((p->p_pptr->p_procsig->ps_flag &
 					PS_NOCLDSTOP) == 0) {
@@ -1478,7 +1487,7 @@
 		/* NOTREACHED */
 	} else {
 		/* Not in "NORMAL" state. discard the signal. */
-		SIGDELSET(p->p_siglist, sig);
+		signal_delete(p, NULL, sig);
 		goto out;
 	}
 
@@ -1553,7 +1562,7 @@
 			 * be awakened.
 			 */
 			if ((prop & SA_CONT) && action == SIG_DFL) {
-				SIGDELSET(p->p_siglist, sig);
+				signal_delete(p, NULL, sig);
 				return;
 			}
 
@@ -1609,13 +1618,13 @@
 	for (;;) {
 		int traced = (p->p_flag & P_TRACED) || (p->p_stops & S_SIG);
 
-		mask = p->p_siglist;
+		ksiginfo_to_sigset_t(p, &mask);
 		SIGSETNAND(mask, p->p_sigmask);
 		if (p->p_flag & P_PPWAIT)
 			SIG_STOPSIGMASK(mask);
 		if (SIGISEMPTY(mask))		/* no signal to send */
 			return (0);
-		sig = sig_ffs(&mask);
+		sig = signal_queued_mask(p, mask);
 		prop = sigprop(sig);
 
 		_STOPEVENT(p, S_SIG, sig);
@@ -1625,7 +1634,7 @@
 		 * only if P_TRACED was on when they were posted.
 		 */
 		if (SIGISMEMBER(p->p_sigignore, sig) && (traced == 0)) {
-			SIGDELSET(p->p_siglist, sig);
+			signal_delete(p, NULL, sig);
 			continue;
 		}
 		if (p->p_flag & P_TRACED && (p->p_flag & P_PPWAIT) == 0) {
@@ -1660,16 +1669,16 @@
 			 * then it will leave it in p->p_xstat;
 			 * otherwise we just look for signals again.
 			 */
-			SIGDELSET(p->p_siglist, sig);	/* clear old signal */
+			signal_delete(p, NULL, sig);	/* clear old signal */
 			sig = p->p_xstat;
 			if (sig == 0)
 				continue;
 
 			/*
-			 * Put the new signal into p_siglist.  If the
-			 * signal is being masked, look for other signals.
+			 * Put the new signal into p_sigq.  If the signal
+			 * is being masked, look for other signals.
 			 */
-			SIGADDSET(p->p_siglist, sig);
+			psignal(p, sig);
 			if (SIGISMEMBER(p->p_sigmask, sig))
 				continue;
 			signotify(p);
@@ -1759,7 +1768,7 @@
 			 */
 			return (sig);
 		}
-		SIGDELSET(p->p_siglist, sig);		/* take the signal! */
+		signal_delete(p, NULL, sig);		/* take the signal! */
 	}
 	/* NOTREACHED */
 }
@@ -1791,16 +1800,16 @@
 {
 	struct thread *td = curthread;
 	register struct proc *p = td->td_proc;
+	struct ksiginfo *ksi;
 	struct sigacts *ps;
 	sig_t action;
 	sigset_t returnmask;
-	int code;
 
 	KASSERT(sig != 0, ("postsig"));
 
 	PROC_LOCK_ASSERT(p, MA_OWNED);
 	ps = p->p_sigacts;
-	SIGDELSET(p->p_siglist, sig);
+	ksiginfo_dequeue(&ksi, p, sig);
 	action = ps->ps_sigact[_SIG_IDX(sig)];
 #ifdef KTRACE
 	if (KTRPOINT(td, KTR_PSIG))
@@ -1814,6 +1823,7 @@
 		 * Default action, where the default is to kill
 		 * the process.  (Other cases were ignored above.)
 		 */
+		ksiginfo_destroy(&ksi);
 		sigexit(td, sig);
 		/* NOTREACHED */
 	} else {
@@ -1852,17 +1862,13 @@
 			ps->ps_sigact[_SIG_IDX(sig)] = SIG_DFL;
 		}
 		p->p_stats->p_ru.ru_nsignals++;
-		if (p->p_sig != sig) {
-			code = 0;
-		} else {
-			code = p->p_code;
-			p->p_code = 0;
-			p->p_sig = 0;
-		}
 		if (p->p_flag & P_KSES)
-			if (signal_upcall(p, sig))
+			if (signal_upcall(p, sig)) {
+				ksiginfo_destroy(&ksi);
 				return;
-		(*p->p_sysent->sv_sendsig)(action, sig, &returnmask, code);
+			}
+		(*p->p_sysent->sv_sendsig)(action, ksi, &returnmask);
+		ksiginfo_destroy(&ksi);
 	}
 }
 
@@ -1901,7 +1907,6 @@
 	PROC_LOCK_ASSERT(p, MA_OWNED);
 	p->p_acflag |= AXSIG;
 	if (sigprop(sig) & SA_CORE) {
-		p->p_sig = sig;
 		/*
 		 * Log signals which would cause core dumps
 		 * (Log as LOG_INFO to appease those who don't want
diff -Nrdu -x *CVS* -x *dev* sys/kern/subr_sigq.c kernel/kern/subr_sigq.c
--- sys/kern/subr_sigq.c	Wed Dec 31 18:00:00 1969
+++ kernel/kern/subr_sigq.c	Sat Oct  5 01:21:00 2002
@@ -0,0 +1,323 @@
+/*-
+ * Copyright (c) 2002 New Gold Technology.  All rights reserved.
+ * Copyright (c) 2002 Juli Mallett.  All rights reserved.
+ *
+ * This software was written by Juli Mallett <jmallett@FreeBSD.org> for the
+ * FreeBSD project.  Redistribution and use in source and binary forms, with
+ * or without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * 1. Redistribution of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ * 2. Redistribution in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD: src/sys/kern/subr_sigq.c,v 1.4 2002/10/01 03:19:49 jmallett Exp $
+ */
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/signalvar.h>
+#include <sys/proc.h>
+#include <sys/errno.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/mutex.h>
+#include <sys/signal.h>
+#include <sys/ksiginfo.h>
+
+MALLOC_DECLARE(M_KSIGINFO);
+MALLOC_DEFINE(M_KSIGINFO, "ksiginfos", "Kernel signal info structures");
+
+int
+ksiginfo_alloc(struct ksiginfo **ksip, struct proc *p, int signo)
+{
+	int error;
+	struct ksiginfo *ksi;
+
+	error = 0;
+
+	PROC_LOCK_ASSERT(p, MA_NOTOWNED);
+	ksi = malloc(sizeof *ksi, M_KSIGINFO, M_ZERO | M_NOWAIT);
+	if (ksi == NULL) {
+		PROC_LOCK(p);
+		p->p_suicide = 1;
+		PROC_UNLOCK(p);
+	}
+	ksi->ksi_signo = signo;
+	if (curproc != NULL) {
+		ksi->ksi_pid = curproc->p_pid;
+		ksi->ksi_ruid = curproc->p_ucred->cr_uid;
+	}
+	*ksip = ksi;
+	return (error);
+}
+
+int
+ksiginfo_dequeue(struct ksiginfo **ksip, struct proc *p, int signo)
+{
+	int error;
+	struct ksiginfo *ksi;
+
+	error = 0;
+	ksi = NULL;
+
+	PROC_LOCK_ASSERT(p, MA_OWNED);
+	if (TAILQ_EMPTY(&p->p_sigq)) {
+		error = EDOOFUS;
+		goto out;
+	}
+	/*
+	 * If we have no signo, get the lowest numbered one that's pending.
+	 * XXX This should probably be duplicated from signal_pending, using
+	 * a pointer to a struct ksiginfo for the 'lowest' value, to avoid
+	 * traversing the list the same amount twice.
+	 */
+	if (!signo)
+		signo = signal_pending(p, 0);
+	TAILQ_FOREACH(ksi, &p->p_sigq, ksi_queue) {
+		if (ksi->ksi_signo == signo)
+			goto out;
+	}
+	error = ESRCH;
+	ksi = NULL;
+out:
+	if (ksi != NULL)
+		TAILQ_REMOVE(&p->p_sigq, ksi, ksi_queue);
+	*ksip = ksi;
+	return (error);
+}
+
+int
+ksiginfo_destroy(struct ksiginfo **ksip)
+{
+	int error;
+	struct ksiginfo *ksi;
+
+	error = 0;
+
+	ksi = *ksip;
+	if (ksi == NULL) {
+		error = EDOOFUS;
+		goto out;
+	}
+	free(ksi, M_KSIGINFO);
+	ksi = NULL;
+out:
+	*ksip = ksi;
+	return (error);
+}
+
+int
+ksiginfo_to_siginfo_t(struct ksiginfo *ksi, siginfo_t *si)
+{
+	int error;
+
+	error = 0;
+
+	si->si_addr = ksi->ksi_addr;
+	si->si_code = ksi->ksi_code;
+	si->si_errno = ksi->ksi_errno;
+	si->si_signo = ksi->ksi_signo;
+	si->si_status = ksi->ksi_status;
+	si->si_uid = ksi->ksi_ruid;
+	si->si_pid = ksi->ksi_pid;
+
+	return (error);
+}
+
+int
+ksiginfo_to_sigset_t(struct proc *p, sigset_t *setp)
+{
+	int error;
+	sigset_t set;
+	struct ksiginfo *ksi;
+
+	error = 0;
+	SIGEMPTYSET(set);
+
+	PROC_LOCK_ASSERT(p, MA_OWNED);
+	/*
+	 * We could set EDOOFUS here, however if there are no queued
+	 * signals, then an empty signal set _is_ valid.
+	 */
+	if (TAILQ_EMPTY(&p->p_sigq))
+		goto out;
+	TAILQ_FOREACH(ksi, &p->p_sigq, ksi_queue)
+		SIGADDSET(set, ksi->ksi_signo);
+out:
+	*setp = set;
+	return (error);
+}
+
+int
+signal_add(struct proc *p, struct ksiginfo *ksi, int signo)
+{
+	int error;
+	
+	error = 0;
+
+	PROC_LOCK_ASSERT(p, MA_OWNED);
+	if (ksi == NULL) {
+		PROC_UNLOCK(p);
+		error = ksiginfo_alloc(&ksi, p, signo);
+		PROC_LOCK(p);
+		if (error)
+			return (error);
+	}
+	TAILQ_INSERT_HEAD(&p->p_sigq, ksi, ksi_queue);
+out:
+	return (error);
+}
+
+int
+signal_delete(struct proc *p, struct ksiginfo *ksi, int signo)
+{
+	int error;
+
+	error = 0;
+
+	PROC_LOCK_ASSERT(p, MA_OWNED);
+	if (ksi == NULL) {
+		while (signal_queued(p, signo)) {
+			error = ksiginfo_dequeue(&ksi, p, signo);
+			if (error)
+				return (error);
+			error = ksiginfo_destroy(&ksi);
+			if (error)
+				return (error);
+		}
+	}
+out:
+	if (ksi != NULL) {
+		TAILQ_REMOVE(&p->p_sigq, ksi, ksi_queue);
+		ksiginfo_destroy(&ksi);
+	}
+	return (error);
+}
+
+int
+signal_delete_mask(struct proc *p, int mask)
+{
+	int error;
+	struct ksiginfo *ksi, *prev;
+
+	error = 0;
+	ksi = prev = NULL;
+
+	PROC_LOCK_ASSERT(p, MA_OWNED);
+	if (TAILQ_EMPTY(&p->p_sigq))
+		goto out;
+	TAILQ_FOREACH(ksi, &p->p_sigq, ksi_queue) {
+		if (prev != NULL) {
+			TAILQ_REMOVE(&p->p_sigq, prev, ksi_queue);
+			error = ksiginfo_destroy(&prev);
+			if (error)
+				return (error);
+		}
+		if (sigmask(ksi->ksi_signo) & mask)
+			prev = ksi;
+	}
+	if (prev != NULL) {
+		TAILQ_REMOVE(&p->p_sigq, prev, ksi_queue);
+		error = ksiginfo_destroy(&prev);
+		if (error)
+			return (error);
+	}
+out:
+	return (error);
+}
+
+int
+signal_pending(struct proc *p)
+{
+	int error, pending;
+	sigset_t set;
+
+	error = 0;
+	pending = 0;
+
+	PROC_LOCK_ASSERT(p, MA_OWNED);
+	if (TAILQ_EMPTY(&p->p_sigq))
+		goto out;
+	if (p->p_flag & P_TRACED) {
+		pending = 1;
+		goto out;
+	}
+	error = ksiginfo_to_sigset_t(p, &set);
+	if (error)
+		goto out;
+	pending = !sigsetmasked(&set, &p->p_sigmask);
+	if (pending)
+		goto out;
+out:
+	return (pending);
+}
+
+int
+signal_queued(struct proc *p, int signo)
+{
+	int error, lowest, pending;
+	struct ksiginfo *ksi;
+
+	error = 0;
+	lowest = 0;
+	pending = 0;
+	ksi = NULL;
+
+	PROC_LOCK_ASSERT(p, MA_OWNED);
+	if (TAILQ_EMPTY(&p->p_sigq))
+		goto out;
+	TAILQ_FOREACH(ksi, &p->p_sigq, ksi_queue) {
+		pending = ksi->ksi_signo;
+
+		if (signo == pending)
+			goto out;
+		else if (signo == 0) {
+			if (pending < lowest)
+				lowest = pending;
+		}
+	}
+	if (signo)
+		pending = 0;
+	else
+		pending = lowest;
+out:
+	return (pending);
+}
+
+int
+signal_queued_mask(struct proc *p, sigset_t mask)
+{
+	int pending;
+	struct ksiginfo *ksi;
+
+	pending = 0;
+	ksi = NULL;
+
+	PROC_LOCK_ASSERT(p, MA_OWNED);
+	if (TAILQ_EMPTY(&p->p_sigq))
+		goto out;
+	TAILQ_FOREACH(ksi, &p->p_sigq, ksi_queue) {
+		if (SIGISMEMBER(mask, ksi->ksi_signo)) {
+			pending = ksi->ksi_signo;
+			goto out;
+		}
+	}
+out:
+	return (pending);
+}
diff -Nrdu -x *CVS* -x *dev* sys/kern/tty.c kernel/kern/tty.c
--- sys/kern/tty.c	Tue Oct  1 12:15:52 2002
+++ kernel/kern/tty.c	Sat Oct  5 01:21:00 2002
@@ -44,7 +44,7 @@
  * SUCH DAMAGE.
  *
  *	@(#)tty.c	8.8 (Berkeley) 1/21/94
- * $FreeBSD: src/sys/kern/tty.c,v 1.188 2002/10/01 17:15:52 jmallett Exp $
+ * $FreeBSD: src/sys/kern/tty.c,v 1.187 2002/10/01 00:07:27 jmallett Exp $
  */
 
 /*-
@@ -102,6 +102,7 @@
 #include <sys/malloc.h>
 #include <sys/filedesc.h>
 #include <sys/sysctl.h>
+#include <sys/ksiginfo.h>
 
 #include <vm/vm.h>
 #include <vm/pmap.h>
@@ -1841,21 +1842,24 @@
 ttycheckoutq(struct tty *tp, int wait)
 {
 	int hiwat, s;
-	sigset_t oldmask;
+	sigset_t oldmask, newmask;
 
 	hiwat = tp->t_ohiwat;
 	SIGEMPTYSET(oldmask);
 	s = spltty();
 	if (wait)
-		oldmask = curproc->p_siglist;
+		ksiginfo_to_sigset_t(curproc, &oldmask);
 	if (tp->t_outq.c_cc > hiwat + OBUFSIZ + 100)
 		while (tp->t_outq.c_cc > hiwat) {
 			ttstart(tp);
 			if (tp->t_outq.c_cc <= hiwat)
 				break;
-			if (!(wait && SIGSETEQ(curproc->p_siglist, oldmask))) {
-				splx(s);
-				return (0);
+			if (!wait) {
+				ksiginfo_to_sigset_t(curproc, &newmask);
+				if (SIGSETEQ(newmask, oldmask)) {
+					splx(s);
+					return (0);
+				}
 			}
 			SET(tp->t_state, TS_SO_OLOWAT);
 			tsleep(TSA_OLOWAT(tp), PZERO - 1, "ttoutq", hz);
diff -Nrdu -x *CVS* -x *dev* sys/netncp/ncp_ncp.c kernel/netncp/ncp_ncp.c
--- sys/netncp/ncp_ncp.c	Tue Oct  1 12:15:52 2002
+++ kernel/netncp/ncp_ncp.c	Sat Oct  5 01:21:30 2002
@@ -29,7 +29,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD: src/sys/netncp/ncp_ncp.c,v 1.11 2002/10/01 17:15:52 jmallett Exp $
+ * $FreeBSD: src/sys/netncp/ncp_ncp.c,v 1.10 2002/09/30 20:48:28 jmallett Exp $
  *
  * Core of NCP protocol
  */
@@ -42,6 +42,7 @@
 #include <sys/sysctl.h>
 #include <sys/mbuf.h>
 #include <sys/uio.h>
+#include <sys/ksiginfo.h>
 
 #include <netipx/ipx.h>
 #include <netipx/ipx_var.h>
@@ -80,11 +81,15 @@
 
 	if (p == NULL)
 		return 0;
-	tmpset = p->p_siglist;
+	PROC_LOCK(p);
+	ksiginfo_to_sigset_t(p, &tmpset);
 	SIGSETNAND(tmpset, p->p_sigmask);
 	SIGSETNAND(tmpset, p->p_sigignore);
-	if (SIGNOTEMPTY(p->p_siglist) && NCP_SIGMASK(tmpset))
+	if (signal_queued(p, 0) && NCP_SIGMASK(tmpset)) {
+		PROC_UNLOCK(p);
                 return EINTR;
+	}
+	PROC_UNLOCK(p);
 	return 0;
 }
 
diff -Nrdu -x *CVS* -x *dev* sys/netsmb/smb_subr.c kernel/netsmb/smb_subr.c
--- sys/netsmb/smb_subr.c	Tue Oct  1 12:15:53 2002
+++ kernel/netsmb/smb_subr.c	Sat Oct  5 01:21:32 2002
@@ -29,7 +29,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD: src/sys/netsmb/smb_subr.c,v 1.9 2002/10/01 17:15:53 jmallett Exp $
+ * $FreeBSD: src/sys/netsmb/smb_subr.c,v 1.8 2002/09/30 20:48:29 jmallett Exp $
  */
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -42,6 +42,7 @@
 #include <sys/socket.h>
 #include <sys/signalvar.h>
 #include <sys/mbuf.h>
+#include <sys/ksiginfo.h>
 
 #include <sys/iconv.h>
 
@@ -75,11 +76,15 @@
 
 	if (p == NULL)
 		return 0;
-	tmpset = p->p_siglist;
+	PROC_LOCK(p);
+	ksiginfo_to_sigset_t(p, &tmpset);
 	SIGSETNAND(tmpset, p->p_sigmask);
 	SIGSETNAND(tmpset, p->p_sigignore);
-	if (SIGNOTEMPTY(p->p_siglist) && SMB_SIGMASK(tmpset))
+	if (signal_queued(p, 0) && SMB_SIGMASK(tmpset)) {
+		PROC_UNLOCK(p);
                 return EINTR;
+	}
+	PROC_UNLOCK(p);
 	return 0;
 }
 
diff -Nrdu -x *CVS* -x *dev* sys/nfsclient/nfs_socket.c kernel/nfsclient/nfs_socket.c
--- sys/nfsclient/nfs_socket.c	Tue Oct  1 12:15:53 2002
+++ kernel/nfsclient/nfs_socket.c	Sat Oct  5 01:21:34 2002
@@ -37,7 +37,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/nfsclient/nfs_socket.c,v 1.90 2002/10/01 17:15:53 jmallett Exp $");
+__FBSDID("$FreeBSD: src/sys/nfsclient/nfs_socket.c,v 1.89 2002/09/30 21:15:33 jmallett Exp $");
 
 /*
  * Socket operations for use by nfs
@@ -61,6 +61,7 @@
 #include <sys/sysctl.h>
 #include <sys/syslog.h>
 #include <sys/vnode.h>
+#include <sys/ksiginfo.h>
 
 #include <netinet/in.h>
 #include <netinet/tcp.h>
@@ -1239,11 +1240,15 @@
 		return (0);
 
 	p = td->td_proc;
-	tmpset = p->p_siglist;
+	PROC_LOCK(p);
+	ksiginfo_to_sigset_t(p, &tmpset);
 	SIGSETNAND(tmpset, p->p_sigmask);
 	SIGSETNAND(tmpset, p->p_sigignore);
-	if (SIGNOTEMPTY(p->p_siglist) && NFSINT_SIGMASK(tmpset))
+	if (signal_queued(p, 0) && NFSINT_SIGMASK(tmpset)) {
+		PROC_UNLOCK(p);
 		return (EINTR);
+	}
+	PROC_UNLOCK(p);
 
 	return (0);
 }
diff -Nrdu -x *CVS* -x *dev* sys/sys/ksiginfo.h kernel/sys/ksiginfo.h
--- sys/sys/ksiginfo.h	Wed Dec 31 18:00:00 1969
+++ kernel/sys/ksiginfo.h	Sat Oct  5 01:22:02 2002
@@ -0,0 +1,78 @@
+/*-
+ * Copyright (c) 2002 New Gold Technology.  All rights reserved.
+ * Copyright (c) 2002 Juli Mallett.  All rights reserved.
+ *
+ * This software was written by Juli Mallett <jmallett@FreeBSD.org> for the
+ * FreeBSD project.  Redistribution and use in source and binary forms, with
+ * or without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * 1. Redistribution of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ * 2. Redistribution in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * $FreeBSD: src/sys/sys/ksiginfo.h,v 1.3 2002/10/01 00:16:17 jmallett Exp $
+ */
+
+#ifndef	_SYS_KSIGINFO_H_
+#define	_SYS_KSIGINFO_H_
+
+#ifndef	_KERNEL
+#error "no user-serviceable parts inside"
+#endif
+
+#include <sys/signal.h>
+#include <sys/queue.h>
+
+/*
+ * Structures and prototypes for working with the in-kernel representation
+ * of pending signals, and all the information we have about them.
+ */
+
+/*
+ * This is pushed to userland in the form of a siginfo_t, which is POSIX
+ * defined.  This is for in-kernel representations only, and has no ABI
+ * consumers.
+ */
+struct ksiginfo {
+	TAILQ_ENTRY(ksiginfo)	 ksi_queue;	/* Entry in the signal queue. */
+	void			*ksi_addr;	/* [Fault] address. */
+	int			 ksi_code;	/* [Trap] code. */
+	int			 ksi_errno;	/* Error number. */
+	int			 ksi_signo;	/* Signal number. */
+	int			 ksi_status;	/* Exit status (SIGCHLD). */
+	uid_t			 ksi_ruid;	/* Real UID of sender. */
+	pid_t			 ksi_pid;	/* PID of sender. */
+};
+
+struct proc;
+
+__BEGIN_DECLS;
+int ksiginfo_alloc(struct ksiginfo **, struct proc *, int);
+int ksiginfo_dequeue(struct ksiginfo **, struct proc *, int);
+int ksiginfo_destroy(struct ksiginfo **);
+int ksiginfo_to_siginfo_t(struct ksiginfo *, siginfo_t *);
+int ksiginfo_to_sigset_t(struct proc *, sigset_t *);
+int signal_add(struct proc *, struct ksiginfo *, int);
+int signal_delete(struct proc *, struct ksiginfo *, int);
+int signal_delete_mask(struct proc *, int);
+int signal_pending(struct proc *);
+int signal_queued(struct proc *, int);
+int signal_queued_mask(struct proc *, sigset_t);
+__END_DECLS;
+
+#endif /* !_SYS_KSIGINFO_H_ */
diff -Nrdu -x *CVS* -x *dev* sys/sys/proc.h kernel/sys/proc.h
--- sys/sys/proc.h	Tue Oct  1 12:15:53 2002
+++ kernel/sys/proc.h	Sat Oct  5 01:22:05 2002
@@ -36,7 +36,7 @@
  * SUCH DAMAGE.
  *
  *	@(#)proc.h	8.15 (Berkeley) 5/19/95
- * $FreeBSD: src/sys/sys/proc.h,v 1.264 2002/10/01 17:15:53 jmallett Exp $
+ * $FreeBSD: src/sys/sys/proc.h,v 1.263 2002/10/01 00:07:28 jmallett Exp $
  */
 
 #ifndef _SYS_PROC_H_
@@ -497,6 +497,7 @@
 	TAILQ_HEAD(, ksegrp) p_ksegrps;	/* (kg_ksegrp) All KSEGs. */
 	TAILQ_HEAD(, thread) p_threads;	/* (td_plist) Threads. (shortcut) */
 	TAILQ_HEAD(, thread) p_suspended; /* (td_runq) suspended threads */
+	TAILQ_HEAD(, ksiginfo) p_sigq;	/* (c) Queued signals. */
 	struct ucred	*p_ucred;	/* (c) Process owner's identity. */
 	struct filedesc	*p_fd;		/* (b) Ptr to open files structure. */
 					/* Accumulated stats for all KSEs? */
@@ -535,17 +536,15 @@
 	u_int		p_swtime;	/* (j) Time swapped in or out. */
 	struct itimerval p_realtimer;	/* (h?/k?) Alarm timer. */
 	struct bintime	p_runtime;	/* (j) Real time. */
+	int		p_suicide;	/* (c) Commit signal suicide. */
 	int		p_traceflag;	/* (o) Kernel trace points. */
 	struct vnode	*p_tracep;	/* (c + o) Trace to vnode. */
-	sigset_t	p_siglist;	/* (c) Sigs arrived, not delivered. */
 	struct vnode	*p_textvp;	/* (b) Vnode of executable. */
 	char		p_lock;		/* (c) Proclock (prevent swap) count. */
 	struct klist p_klist;		/* (c) Knotes attached to this proc. */
 	struct sigiolst	p_sigiolst;	/* (c) List of sigio sources. */
 	int		p_sigparent;	/* (c) Signal to parent on exit. */
 	sigset_t	p_oldsigmask;	/* (c) Saved mask from pre sigpause. */
-	int		p_sig;		/* (n) For core dump/debugger XXX. */
-	u_long		p_code;		/* (n) For core dump/debugger XXX. */
 	u_int		p_stops;	/* (c) Stop event bitmask. */
 	u_int		p_stype;	/* (c) Stop event type. */
 	char		p_step;		/* (c) Process is stopped. */
diff -Nrdu -x *CVS* -x *dev* sys/sys/signalvar.h kernel/sys/signalvar.h
--- sys/sys/signalvar.h	Sat Jun 29 12:26:22 2002
+++ kernel/sys/signalvar.h	Sat Oct  5 01:22:06 2002
@@ -189,12 +189,6 @@
 
 #ifdef _KERNEL
 
-/* Return nonzero if process p has an unmasked pending signal. */
-#define	SIGPENDING(p)							\
-	(!SIGISEMPTY((p)->p_siglist) &&					\
-	    (!sigsetmasked(&(p)->p_siglist, &(p)->p_sigmask) ||		\
-	    (p)->p_flag & P_TRACED))
-
 /*
  * Return the value of the pseudo-expression ((*set & ~*mask) != 0).  This
  * is an optimized version of SIGISEMPTY() on a temporary variable
@@ -212,11 +206,12 @@
 	return (1);
 }
 
+struct ksiginfo;
+struct mtx;
 struct pgrp;
-struct thread;
 struct proc;
 struct sigio;
-struct mtx;
+struct thread;
 
 extern int sugid_coredump;	/* Sysctl variable kern.sugid_coredump */
 extern struct mtx	sigio_lock;
@@ -251,7 +246,7 @@
 /*
  * Machine-dependent functions:
  */
-void	sendsig(sig_t action, int sig, sigset_t *retmask, u_long code);
+void	sendsig(sig_t action, struct ksiginfo *, sigset_t *retmask);
 
 #endif /* _KERNEL */
 
diff -Nrdu -x *CVS* -x *dev* sys/sys/sysent.h kernel/sys/sysent.h
--- sys/sys/sysent.h	Sun Sep  1 16:41:24 2002
+++ kernel/sys/sysent.h	Sat Oct  5 01:22:06 2002
@@ -51,8 +51,9 @@
 #define SCARG(p,k)	((p)->k)	/* get arg from args pointer */
   /* placeholder till we integrate rest of lite2 syscallargs changes XXX */
 
-struct image_params;
 struct __sigset;
+struct ksiginfo;
+struct image_params;
 struct trapframe;
 struct vnode;
 
@@ -68,8 +69,8 @@
 					/* translate trap-to-signal mapping */
 	int		(*sv_fixup)(register_t **, struct image_params *);
 					/* stack fixup function */
-	void		(*sv_sendsig)(void (*)(int), int, struct __sigset *,
-			    u_long);	/* send signal */
+	void		(*sv_sendsig)(void (*)(int), struct ksiginfo *,
+			    struct __sigset *);	/* send signal */
 	char 		*sv_sigcode;	/* start of sigtramp code */
 	int 		*sv_szsigcode;	/* size of sigtramp code */
 	void		(*sv_prepsyscall)(struct trapframe *, int *, u_int *,

%%%

Thanks,
juli.
-- 
Juli Mallett <jmallett@FreeBSD.org>       | FreeBSD: The Power To Serve
Will break world for fulltime employment. | finger jmallett@FreeBSD.org
http://people.FreeBSD.org/~jmallett/      | Support my FreeBSD hacking!

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




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