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>
