summaryrefslogtreecommitdiffstats
path: root/sys/kern
diff options
context:
space:
mode:
authorjmallett <jmallett@FreeBSD.org>2002-09-30 20:20:22 +0000
committerjmallett <jmallett@FreeBSD.org>2002-09-30 20:20:22 +0000
commit0341f71df178fd346332ced28efb677a6ef39414 (patch)
tree44cc85d6d7a465b4410e0fa06f9f5a1b21bc40b6 /sys/kern
parente70c6b99c8b8b510eaef402242dd8cb86e300c6f (diff)
downloadFreeBSD-src-0341f71df178fd346332ced28efb677a6ef39414.zip
FreeBSD-src-0341f71df178fd346332ced28efb677a6ef39414.tar.gz
First half of implementation of ksiginfo, signal queues, and such. This
gets signals operating based on a TailQ, and is good enough to run X11, GNOME, and do job control. There are some intricate parts which could be more refined to match the sigset_t versions, but those require further evaluation of directions in which our signal system can expand and contract to fit our needs. After this has been in the tree for a while, I will make in kernel API changes, most notably to trapsignal(9) and sendsig(9), to use ksiginfo more robustly, such that we can actually pass information with our (queued) signals to the userland. That will also result in using a struct ksiginfo pointer, rather than a signal number, in a lot of kern_sig.c, to refer to an individual pending signal queue member, but right now there is no defined behaviour for such. CODAFS is unfinished in this regard because the logic is unclear in some places. Sponsored by: New Gold Technology Reviewed by: bde, tjr, jake [an older version, logic similar]
Diffstat (limited to 'sys/kern')
-rw-r--r--sys/kern/init_main.c2
-rw-r--r--sys/kern/kern_exit.c9
-rw-r--r--sys/kern/kern_fork.c1
-rw-r--r--sys/kern/kern_kthread.c17
-rw-r--r--sys/kern/kern_proc.c5
-rw-r--r--sys/kern/kern_sig.c64
-rw-r--r--sys/kern/subr_sigq.c301
-rw-r--r--sys/kern/subr_trap.c4
-rw-r--r--sys/kern/tty.c14
9 files changed, 372 insertions, 45 deletions
diff --git a/sys/kern/init_main.c b/sys/kern/init_main.c
index 49bb739..d58e7df 100644
--- a/sys/kern/init_main.c
+++ b/sys/kern/init_main.c
@@ -348,6 +348,8 @@ proc0_init(void *dummy __unused)
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);
session0.s_count = 1;
diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c
index 1725d54..572aab3 100644
--- a/sys/kern/kern_exit.c
+++ b/sys/kern/kern_exit.c
@@ -67,6 +67,7 @@
#ifdef KTRACE
#include <sys/ktrace.h>
#endif
+#include <sys/ksiginfo.h>
#include <vm/vm.h>
#include <vm/vm_extern.h>
@@ -244,7 +245,7 @@ exit1(td, rv)
*/
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 @@ exit1(td, rv)
*/
if (p->p_flag & P_KTHREAD)
wakeup(p);
+
+ /*
+ * And now, kill off its signals...
+ */
+ signal_delete(p, NULL, 0);
+
PROC_UNLOCK(p);
/*
diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c
index da7ca7d..c8182f9 100644
--- a/sys/kern/kern_fork.c
+++ b/sys/kern/kern_fork.c
@@ -605,6 +605,7 @@ again:
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 --git a/sys/kern/kern_kthread.c b/sys/kern/kern_kthread.c
index 08ef71f..95e9a68 100644
--- a/sys/kern/kern_kthread.c
+++ b/sys/kern/kern_kthread.c
@@ -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,16 +145,16 @@ kthread_suspend(struct proc *p, int timo)
{
/*
* 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
@@ -168,9 +169,9 @@ kthread_resume(struct proc *p)
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 +179,9 @@ void
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 --git a/sys/kern/kern_proc.c b/sys/kern/kern_proc.c
index 633c66e..e7fce8a 100644
--- a/sys/kern/kern_proc.c
+++ b/sys/kern/kern_proc.c
@@ -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 @@ kse_create(struct thread *td, struct kse_create_args *uap)
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 @@ fill_kinfo_proc(p, kp)
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 --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c
index f6fa38b..ada2016 100644
--- a/sys/kern/kern_sig.c
+++ b/sys/kern/kern_sig.c
@@ -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.
@@ -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 @@ static int do_coredump = 1;
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 @@ cursig(struct thread *td)
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 @@ signotify(struct proc *p)
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 @@ kern_sigaction(td, sig, act, oact, old)
(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 @@ execsigs(p)
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 @@ sigpending(td, uap)
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 @@ osigpending(td, uap)
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);
@@ -1308,7 +1316,7 @@ psignal(p, sig)
}
if (prop & SA_CONT)
- SIG_STOPSIGMASK(p->p_siglist);
+ signal_delete_mask(p, stopmask);
if (prop & SA_STOP) {
/*
@@ -1321,10 +1329,10 @@ psignal(p, sig)
(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 +1370,10 @@ psignal(p, sig)
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 +1381,7 @@ psignal(p, sig)
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 +1411,7 @@ psignal(p, sig)
* 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 +1445,7 @@ psignal(p, sig)
/*
* 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 +1469,7 @@ psignal(p, sig)
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 +1486,7 @@ psignal(p, sig)
/* NOTREACHED */
} else {
/* Not in "NORMAL" state. discard the signal. */
- SIGDELSET(p->p_siglist, sig);
+ signal_delete(p, NULL, sig);
goto out;
}
@@ -1553,7 +1561,7 @@ tdsignal(struct thread *td, int sig, sig_t action)
* be awakened.
*/
if ((prop & SA_CONT) && action == SIG_DFL) {
- SIGDELSET(p->p_siglist, sig);
+ signal_delete(p, NULL, sig);
return;
}
@@ -1609,13 +1617,13 @@ issignal(td)
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 +1633,7 @@ issignal(td)
* 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 +1668,16 @@ issignal(td)
* 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 +1767,7 @@ issignal(td)
*/
return (sig);
}
- SIGDELSET(p->p_siglist, sig); /* take the signal! */
+ signal_delete(p, NULL, sig); /* take the signal! */
}
/* NOTREACHED */
}
@@ -1800,7 +1808,7 @@ postsig(sig)
PROC_LOCK_ASSERT(p, MA_OWNED);
ps = p->p_sigacts;
- SIGDELSET(p->p_siglist, sig);
+ signal_delete(p, NULL, sig);
action = ps->ps_sigact[_SIG_IDX(sig)];
#ifdef KTRACE
if (KTRPOINT(td, KTR_PSIG))
diff --git a/sys/kern/subr_sigq.c b/sys/kern/subr_sigq.c
new file mode 100644
index 0000000..fa44fab
--- /dev/null
+++ b/sys/kern/subr_sigq.c
@@ -0,0 +1,301 @@
+/*-
+ * 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$
+ */
+
+#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_DEFINE(M_KSIGINFO, "ksiginfos", "Kernel signal info structures");
+
+int
+ksiginfo_alloc(struct ksiginfo **ksip, int signo)
+{
+ int error;
+ struct ksiginfo *ksi;
+
+ error = 0;
+
+ ksi = malloc(sizeof *ksi, M_KSIGINFO, M_ZERO | M_WAITOK);
+ KASSERT(ksi != NULL, ("ksiginfo_alloc(%d): allocation failed.", signo));
+ if (ksi == NULL) {
+ error = ENOMEM;
+ goto out;
+ }
+ ksi->ksi_signo = signo;
+ if (curproc != NULL) {
+ ksi->ksi_pid = curproc->p_pid;
+ ksi->ksi_ruid = curproc->p_ucred->cr_uid;
+ }
+out:
+ *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 (!signo) {
+ ksi = TAILQ_FIRST(&p->p_sigq);
+ goto out;
+ }
+ 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_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, signo);
+ PROC_LOCK(p);
+ if (error)
+ goto out;
+ }
+ 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)
+ goto out;
+ error = ksiginfo_destroy(&ksi);
+ if (error)
+ goto out;
+ }
+ }
+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)
+ goto out;
+ }
+ if (sigmask(ksi->ksi_signo) & mask)
+ prev = ksi;
+ }
+ if (prev != NULL) {
+ TAILQ_REMOVE(&p->p_sigq, prev, ksi_queue);
+ error = ksiginfo_destroy(&prev);
+ /*
+ * XXX - Could just fall off the bottom...
+ */
+ if (error)
+ goto out;
+ }
+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, pending;
+ struct ksiginfo *ksi;
+
+ error = 0;
+ pending = 0;
+ ksi = NULL;
+
+ PROC_LOCK_ASSERT(p, MA_OWNED);
+ if (TAILQ_EMPTY(&p->p_sigq))
+ goto out;
+ /*
+ * Since we know the queue is not empty, we can just do
+ * pending = TAILQ_FIRST(&p->p_sigq)->ksi_signo, if the
+ * signo is 0, however since we have to use at least one
+ * more TailQ manipulation macro either way, might as well
+ * just do it like this, as I think it optimises better,
+ * even if the failure case is more expensive.
+ */
+ TAILQ_FOREACH(ksi, &p->p_sigq, ksi_queue) {
+ pending = !signo || ksi->ksi_signo == signo;
+ if (pending)
+ goto out;
+ }
+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 --git a/sys/kern/subr_trap.c b/sys/kern/subr_trap.c
index f120141..0a165e9 100644
--- a/sys/kern/subr_trap.c
+++ b/sys/kern/subr_trap.c
@@ -54,6 +54,8 @@
#include <sys/signalvar.h>
#include <sys/systm.h>
#include <sys/vmmeter.h>
+#include <sys/malloc.h>
+#include <sys/ksiginfo.h>
#include <machine/cpu.h>
#include <machine/pcb.h>
@@ -80,7 +82,7 @@ userret(td, frame, oticks)
mtx_lock(&Giant);
PROC_LOCK(p);
mtx_lock_spin(&sched_lock);
- if (SIGPENDING(p) && ((p->p_sflag & PS_NEEDSIGCHK) == 0 ||
+ if (signal_pending(p) && ((p->p_sflag & PS_NEEDSIGCHK) == 0 ||
(td->td_kse->ke_flags & KEF_ASTPENDING) == 0))
printf("failed to set signal flags properly for ast()\n");
mtx_unlock_spin(&sched_lock);
diff --git a/sys/kern/tty.c b/sys/kern/tty.c
index c075a47..590e8de 100644
--- a/sys/kern/tty.c
+++ b/sys/kern/tty.c
@@ -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 @@ int
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);
OpenPOWER on IntegriCloud