summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authormtm <mtm@FreeBSD.org>2003-07-03 19:09:59 +0000
committermtm <mtm@FreeBSD.org>2003-07-03 19:09:59 +0000
commit6f4ee681fdadfbb7008a43761f43ef8fe7d4f5c1 (patch)
tree77ce7442dc945271c4d10bcf0fc6db6bf3b8de78 /sys
parent87561c3aaf68e1a2b0f3365dbecea35358f05f52 (diff)
downloadFreeBSD-src-6f4ee681fdadfbb7008a43761f43ef8fe7d4f5c1.zip
FreeBSD-src-6f4ee681fdadfbb7008a43761f43ef8fe7d4f5c1.tar.gz
Signals sent specifically to a particular thread must
be delivered to that thread, regardless of whether it has it masked or not. Previously, if the targeted thread had the signal masked, it would be put on the processes' siglist. If another thread has the signal umasked or unmasks it before the target, then the thread it was intended for would never receive it. This patch attempts to solve the problem by requiring callers of tdsignal() to say whether the signal is for the thread or for the process. If it is for the process, then normal processing occurs and any thread that has it unmasked can receive it. But if it is destined for a specific thread, it is put on that thread's pending list regardless of whether it is currently masked or not. The new behaviour still needs more work, though. If the signal is reposted for some reason it is always posted back to the thread that handled it because the information regarding the target of the signal has been lost by then. Reviewed by: jdp, jeff, bde (style)
Diffstat (limited to 'sys')
-rw-r--r--sys/kern/kern_kse.c2
-rw-r--r--sys/kern/kern_sig.c26
-rw-r--r--sys/kern/kern_thr.c6
-rw-r--r--sys/kern/kern_thread.c2
-rw-r--r--sys/sys/signalvar.h9
5 files changed, 25 insertions, 20 deletions
diff --git a/sys/kern/kern_kse.c b/sys/kern/kern_kse.c
index bc71b47..4ea5231 100644
--- a/sys/kern/kern_kse.c
+++ b/sys/kern/kern_kse.c
@@ -413,7 +413,7 @@ kse_thr_interrupt(struct thread *td, struct kse_thr_interrupt_args *uap)
if (sig > 0) {
td2->td_flags &= ~TDF_INTERRUPT;
mtx_unlock_spin(&sched_lock);
- tdsignal(td2, sig);
+ tdsignal(td2, sig, SIGTARGET_P);
} else if (sig == 0) {
mtx_unlock_spin(&sched_lock);
} else {
diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c
index 7f5ef68..8d22399 100644
--- a/sys/kern/kern_sig.c
+++ b/sys/kern/kern_sig.c
@@ -95,7 +95,7 @@ static int filt_signal(struct knote *kn, long hint);
static struct thread *sigtd(struct proc *p, int sig, int prop);
static int kern_sigtimedwait(struct thread *td, sigset_t set,
siginfo_t *info, struct timespec *timeout);
-static void do_tdsignal(struct thread *td, int sig);
+static void do_tdsignal(struct thread *td, int sig, sigtarget_t target);
struct filterops sig_filtops =
{ 0, filt_sigattach, filt_sigdetach, filt_signal };
@@ -761,7 +761,7 @@ sigwait(struct thread *td, struct sigwait_args *uap)
/* Repost if we got an error. */
if (error && info.si_signo) {
PROC_LOCK(td->td_proc);
- tdsignal(td, info.si_signo);
+ tdsignal(td, info.si_signo, SIGTARGET_TD);
PROC_UNLOCK(td->td_proc);
}
return (error);
@@ -800,7 +800,7 @@ sigtimedwait(struct thread *td, struct sigtimedwait_args *uap)
/* Repost if we got an error. */
if (error && info.si_signo) {
PROC_LOCK(td->td_proc);
- tdsignal(td, info.si_signo);
+ tdsignal(td, info.si_signo, SIGTARGET_TD);
PROC_UNLOCK(td->td_proc);
} else {
td->td_retval[0] = info.si_signo;
@@ -831,7 +831,7 @@ sigwaitinfo(struct thread *td, struct sigwaitinfo_args *uap)
/* Repost if we got an error. */
if (error && info.si_signo) {
PROC_LOCK(td->td_proc);
- tdsignal(td, info.si_signo);
+ tdsignal(td, info.si_signo, SIGTARGET_TD);
PROC_UNLOCK(td->td_proc);
} else {
td->td_retval[0] = info.si_signo;
@@ -1538,7 +1538,7 @@ trapsignal(struct thread *td, int sig, u_long code)
mtx_unlock(&ps->ps_mtx);
p->p_code = code; /* XXX for core dump/debugger */
p->p_sig = sig; /* XXX to verify code */
- tdsignal(td, sig);
+ tdsignal(td, sig, SIGTARGET_TD);
}
PROC_UNLOCK(p);
}
@@ -1607,21 +1607,21 @@ psignal(struct proc *p, int sig)
*/
td = sigtd(p, sig, prop);
- tdsignal(td, sig);
+ tdsignal(td, sig, SIGTARGET_P);
}
/*
* MPSAFE
*/
void
-tdsignal(struct thread *td, int sig)
+tdsignal(struct thread *td, int sig, sigtarget_t target)
{
sigset_t saved;
struct proc *p = td->td_proc;
if (p->p_flag & P_SA)
saved = p->p_siglist;
- do_tdsignal(td, sig);
+ do_tdsignal(td, sig, target);
if ((p->p_flag & P_SA) && !(p->p_flag & P_SIGEVENT)) {
if (SIGSETEQ(saved, p->p_siglist))
return;
@@ -1634,7 +1634,7 @@ tdsignal(struct thread *td, int sig)
}
static void
-do_tdsignal(struct thread *td, int sig)
+do_tdsignal(struct thread *td, int sig, sigtarget_t target)
{
struct proc *p;
register sig_t action;
@@ -1656,10 +1656,12 @@ do_tdsignal(struct thread *td, int sig)
/*
* If this thread is blocking this signal then we'll leave it in the
- * proc so that we can find it in the first thread that unblocks it.
+ * proc so that we can find it in the first thread that unblocks
+ * it-- unless the signal is meant for the thread and not the process.
*/
- if (SIGISMEMBER(td->td_sigmask, sig))
- siglist = &p->p_siglist;
+ if (target == SIGTARGET_P)
+ siglist = SIGISMEMBER(td->td_sigmask, sig) ?
+ &p->p_siglist : &td->td_siglist;
else
siglist = &td->td_siglist;
diff --git a/sys/kern/kern_thr.c b/sys/kern/kern_thr.c
index dcc0847..92890d0 100644
--- a/sys/kern/kern_thr.c
+++ b/sys/kern/kern_thr.c
@@ -258,11 +258,7 @@ thr_kill(struct thread *td, struct thr_kill_args *uap)
goto out;
}
- /*
- * We need a way to force this to go into this thread's siglist.
- * Until then blocked signals will go to the proc.
- */
- tdsignal(ttd, uap->sig);
+ tdsignal(ttd, uap->sig, SIGTARGET_TD);
out:
PROC_UNLOCK(p);
diff --git a/sys/kern/kern_thread.c b/sys/kern/kern_thread.c
index bc71b47..4ea5231 100644
--- a/sys/kern/kern_thread.c
+++ b/sys/kern/kern_thread.c
@@ -413,7 +413,7 @@ kse_thr_interrupt(struct thread *td, struct kse_thr_interrupt_args *uap)
if (sig > 0) {
td2->td_flags &= ~TDF_INTERRUPT;
mtx_unlock_spin(&sched_lock);
- tdsignal(td2, sig);
+ tdsignal(td2, sig, SIGTARGET_P);
} else if (sig == 0) {
mtx_unlock_spin(&sched_lock);
} else {
diff --git a/sys/sys/signalvar.h b/sys/sys/signalvar.h
index 9e1b908..70b7904 100644
--- a/sys/sys/signalvar.h
+++ b/sys/sys/signalvar.h
@@ -205,6 +205,13 @@ __sigseteq(sigset_t *set1, sigset_t *set2)
#ifdef _KERNEL
+/*
+ * Specifies the target of a signal.
+ * P - Doesn't matter which thread it gets delivered to.
+ * TD - Must be delivered to a specific thread.
+ */
+typedef enum sigtarget_enum { SIGTARGET_P, SIGTARGET_TD } sigtarget_t;
+
/* Return nonzero if process p has an unmasked pending signal. */
#define SIGPENDING(td) \
(!SIGISEMPTY((td)->td_siglist) && \
@@ -267,7 +274,7 @@ void sigexit(struct thread *td, int signum) __dead2;
int sig_ffs(sigset_t *set);
void siginit(struct proc *p);
void signotify(struct thread *td);
-void tdsignal(struct thread *td, int sig);
+void tdsignal(struct thread *td, int sig, sigtarget_t target);
void trapsignal(struct thread *td, int sig, u_long code);
/*
OpenPOWER on IntegriCloud