Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files. =================================================================== RCS file: /ftp/cvs/cvsroot/src/sys/kern/kern_sig.c,v rcsdiff: /ftp/cvs/cvsroot/src/sys/kern/kern_sig.c,v: warning: Unknown phrases like `commitid ...;' are present. retrieving revision 1.279.2.1 retrieving revision 1.279.2.2 diff -u -p -r1.279.2.1 -r1.279.2.2 --- src/sys/kern/kern_sig.c 2008/05/16 02:25:25 1.279.2.1 +++ src/sys/kern/kern_sig.c 2009/05/04 08:13:47 1.279.2.2 @@ -1,4 +1,4 @@ -/* $NetBSD: kern_sig.c,v 1.279.2.1 2008/05/16 02:25:25 yamt Exp $ */ +/* $NetBSD: kern_sig.c,v 1.279.2.2 2009/05/04 08:13:47 yamt Exp $ */ /*- * Copyright (c) 2006, 2007, 2008 The NetBSD Foundation, Inc. @@ -66,14 +66,14 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: kern_sig.c,v 1.279.2.1 2008/05/16 02:25:25 yamt Exp $"); +__KERNEL_RCSID(0, "$NetBSD: kern_sig.c,v 1.279.2.2 2009/05/04 08:13:47 yamt Exp $"); #include "opt_ptrace.h" -#include "opt_multiprocessor.h" #include "opt_compat_sunos.h" #include "opt_compat_netbsd.h" #include "opt_compat_netbsd32.h" #include "opt_pax.h" +#include "opt_sa.h" #define SIGPROP /* include signal properties table */ #include @@ -85,15 +85,17 @@ __KERNEL_RCSID(0, "$NetBSD: kern_sig.c,v #include #include #include -#include #include #include +#include +#include #include #include #include #include #include #include +#include #ifdef PAX_SEGVGUARD #include @@ -104,19 +106,23 @@ __KERNEL_RCSID(0, "$NetBSD: kern_sig.c,v static void ksiginfo_exechook(struct proc *, void *); static void proc_stop_callout(void *); - -int sigunwait(struct proc *, const ksiginfo_t *); -void sigput(sigpend_t *, struct proc *, ksiginfo_t *); -int sigpost(struct lwp *, sig_t, int, int); -int sigchecktrace(sigpend_t **); -void sigswitch(bool, int, int); -void sigrealloc(ksiginfo_t *); +static int sigchecktrace(void); +static int sigpost(struct lwp *, sig_t, int, int, int); +static void sigput(sigpend_t *, struct proc *, ksiginfo_t *); +static int sigunwait(struct proc *, const ksiginfo_t *); +static void sigswitch(bool, int, int); sigset_t contsigmask, stopsigmask, sigcantmask; static pool_cache_t sigacts_cache; /* memory pool for sigacts structures */ static void sigacts_poolpage_free(struct pool *, void *); static void *sigacts_poolpage_alloc(struct pool *, int); static callout_t proc_stop_ch; +static pool_cache_t siginfo_cache; +static pool_cache_t ksiginfo_cache; + +void (*sendsig_sigcontext_vec)(const struct ksiginfo *, const sigset_t *); +int (*coredump_vec)(struct lwp *, const char *) = + (int (*)(struct lwp *, const char *))enosys; static struct pool_allocator sigactspool_allocator = { .pa_alloc = sigacts_poolpage_alloc, @@ -134,11 +140,6 @@ static const char logcoredump[] = static const char lognocoredump[] = "pid %d (%s), uid %d: exited on signal %d (core not dumped, err = %d)\n"; -POOL_INIT(siginfo_pool, sizeof(siginfo_t), 0, 0, 0, "siginfo", - &pool_allocator_nointr, IPL_NONE); -POOL_INIT(ksiginfo_pool, sizeof(ksiginfo_t), 0, 0, 0, "ksiginfo", - NULL, IPL_VM); - /* * signal_init: * @@ -154,6 +155,12 @@ signal_init(void) "sigacts", sizeof(struct sigacts) > PAGE_SIZE ? &sigactspool_allocator : NULL, IPL_NONE, NULL, NULL, NULL); + siginfo_cache = pool_cache_init(sizeof(siginfo_t), 0, 0, 0, + "siginfo", NULL, IPL_NONE, NULL, NULL, NULL); + + ksiginfo_cache = pool_cache_init(sizeof(ksiginfo_t), 0, 0, 0, + "ksiginfo", NULL, IPL_VM, NULL, NULL, NULL); + exechook_establish(ksiginfo_exechook, NULL); callout_init(&proc_stop_ch, CALLOUT_MPSAFE); @@ -422,7 +429,7 @@ ksiginfo_alloc(struct proc *p, ksiginfo_ return ok; } - kp = pool_get(&ksiginfo_pool, flags); + kp = pool_cache_get(ksiginfo_cache, flags); if (kp == NULL) { #ifdef DIAGNOSTIC printf("Out of memory allocating ksiginfo for pid %d\n", @@ -454,7 +461,7 @@ ksiginfo_free(ksiginfo_t *kp) if ((kp->ksi_flags & (KSI_QUEUED | KSI_FROMPOOL)) != KSI_FROMPOOL) return; - pool_put(&ksiginfo_pool, kp); + pool_cache_put(ksiginfo_cache, kp); } /* @@ -472,7 +479,7 @@ ksiginfo_queue_drain0(ksiginfoq_t *kq) while (!CIRCLEQ_EMPTY(kq)) { ksi = CIRCLEQ_FIRST(kq); CIRCLEQ_REMOVE(kq, ksi, ksi_list); - pool_put(&ksiginfo_pool, ksi); + pool_cache_put(ksiginfo_cache, ksi); } } @@ -490,14 +497,8 @@ sigget(sigpend_t *sp, ksiginfo_t *out, i sigset_t tset; /* If there's no pending set, the signal is from the debugger. */ - if (sp == NULL) { - if (out != NULL) { - KSI_INIT(out); - out->ksi_info._signo = signo; - out->ksi_info._code = SI_USER; - } - return signo; - } + if (sp == NULL) + goto out; /* Construct mask from signo, and 'mask'. */ if (signo == 0) { @@ -509,7 +510,7 @@ sigget(sigpend_t *sp, ksiginfo_t *out, i /* If there are no signals pending, that's it. */ if ((signo = firstsig(&tset)) == 0) - return 0; + goto out; } else { KASSERT(sigismember(&sp->sp_set, signo)); } @@ -532,11 +533,12 @@ sigget(sigpend_t *sp, ksiginfo_t *out, i } } +out: /* If there's no siginfo, then manufacture it. */ if (out != NULL) { KSI_INIT(out); out->ksi_info._signo = signo; - out->ksi_info._code = SI_USER; + out->ksi_info._code = SI_NOINFO; } return signo; @@ -545,14 +547,12 @@ sigget(sigpend_t *sp, ksiginfo_t *out, i /* * sigput: * - * Append a new ksiginfo element to the list of pending ksiginfo's, if - * we need to (e.g. SA_SIGINFO was requested). + * Append a new ksiginfo element to the list of pending ksiginfo's. */ -void +static void sigput(sigpend_t *sp, struct proc *p, ksiginfo_t *ksi) { ksiginfo_t *kp; - struct sigaction *sa = &SIGACTION_PS(p->p_sigacts, ksi->ksi_signo); KASSERT(mutex_owned(p->p_lock)); KASSERT((ksi->ksi_flags & KSI_QUEUED) == 0); @@ -560,10 +560,9 @@ sigput(sigpend_t *sp, struct proc *p, ks sigaddset(&sp->sp_set, ksi->ksi_signo); /* - * If siginfo is not required, or there is none, then just mark the - * signal as pending. + * If there is no siginfo, we are done. */ - if ((sa->sa_flags & SA_SIGINFO) == 0 || KSI_EMPTY_P(ksi)) + if (KSI_EMPTY_P(ksi)) return; KASSERT((ksi->ksi_flags & KSI_FROMPOOL) != 0); @@ -671,7 +670,7 @@ siginfo_t * siginfo_alloc(int flags) { - return pool_get(&siginfo_pool, flags); + return pool_cache_get(siginfo_cache, flags); } /* @@ -683,7 +682,7 @@ void siginfo_free(void *arg) { - pool_put(&siginfo_pool, arg); + pool_cache_put(siginfo_cache, arg); } void @@ -696,7 +695,12 @@ getucontext(struct lwp *l, ucontext_t *u ucp->uc_flags = 0; ucp->uc_link = l->l_ctxlink; - ucp->uc_sigmask = l->l_sigmask; +#if KERN_SA + if (p->p_sa != NULL) + ucp->uc_sigmask = p->p_sa->sa_sigmask; + else +#endif /* KERN_SA */ + ucp->uc_sigmask = l->l_sigmask; ucp->uc_flags |= _UC_SIGMASK; /* @@ -718,6 +722,39 @@ getucontext(struct lwp *l, ucontext_t *u mutex_enter(p->p_lock); } +/* + * getucontext_sa: + * Get a ucontext_t for use in SA upcall generation. + * Teweaked version of getucontext(). We 1) do not take p_lock, 2) + * fudge things with uc_link (which is usually NULL for libpthread + * code), and 3) we report an empty signal mask. + */ +void +getucontext_sa(struct lwp *l, ucontext_t *ucp) +{ + ucp->uc_flags = 0; + ucp->uc_link = l->l_ctxlink; + + sigemptyset(&ucp->uc_sigmask); + ucp->uc_flags |= _UC_SIGMASK; + + /* + * The (unsupplied) definition of the `current execution stack' + * in the System V Interface Definition appears to allow returning + * the main context stack. + */ + if ((l->l_sigstk.ss_flags & SS_ONSTACK) == 0) { + ucp->uc_stack.ss_sp = (void *)l->l_proc->p_stackbase; + ucp->uc_stack.ss_size = ctob(l->l_proc->p_vmspace->vm_ssize); + ucp->uc_stack.ss_flags = 0; /* XXX, def. is Very Fishy */ + } else { + /* Simply copy alternate signal execution stack. */ + ucp->uc_stack = l->l_sigstk; + } + ucp->uc_flags |= _UC_STACK; + cpu_getmcontext(l, &ucp->uc_mcontext, &ucp->uc_flags); +} + int setucontext(struct lwp *l, const ucontext_t *ucp) { @@ -844,10 +881,11 @@ kpgsignal(struct pgrp *pgrp, ksiginfo_t KASSERT(!cpu_intr_p()); KASSERT(mutex_owned(proc_lock)); - if (pgrp) - LIST_FOREACH(p, &pgrp->pg_members, p_pglist) - if (checkctty == 0 || p->p_lflag & PL_CONTROLT) - kpsignal(p, ksi, data); + if (__predict_false(pgrp == 0)) + return; + LIST_FOREACH(p, &pgrp->pg_members, p_pglist) + if (checkctty == 0 || p->p_lflag & PL_CONTROLT) + kpsignal(p, ksi, data); } /* @@ -860,6 +898,7 @@ trapsignal(struct lwp *l, ksiginfo_t *ks struct proc *p; struct sigacts *ps; int signo = ksi->ksi_signo; + sigset_t *mask; KASSERT(KSI_TRAP_P(ksi)); @@ -869,16 +908,17 @@ trapsignal(struct lwp *l, ksiginfo_t *ks KASSERT(!cpu_intr_p()); mutex_enter(proc_lock); mutex_enter(p->p_lock); + mask = (p->p_sa != NULL) ? &p->p_sa->sa_sigmask : &l->l_sigmask; ps = p->p_sigacts; if ((p->p_slflag & PSL_TRACED) == 0 && sigismember(&p->p_sigctx.ps_sigcatch, signo) && - !sigismember(&l->l_sigmask, signo)) { + !sigismember(mask, signo)) { mutex_exit(proc_lock); l->l_ru.ru_nsignals++; - kpsendsig(l, ksi, &l->l_sigmask); + kpsendsig(l, ksi, mask); mutex_exit(p->p_lock); ktrpsig(signo, SIGACTION_PS(ps, signo).sa_handler, - &l->l_sigmask, ksi); + mask, ksi); } else { /* XXX for core dump/debugger */ p->p_sigctx.ps_lwp = l->l_lid; @@ -983,21 +1023,26 @@ sigismasked(struct lwp *l, int sig) struct proc *p = l->l_proc; return (sigismember(&p->p_sigctx.ps_sigignore, sig) || - sigismember(&l->l_sigmask, sig)); + sigismember(&l->l_sigmask, sig) +#if KERN_SA + || ((p->p_sa != NULL) && sigismember(&p->p_sa->sa_sigmask, sig)) +#endif /* KERN_SA */ + ); } /* * sigpost: * - * Post a pending signal to an LWP. Returns non-zero if the LWP was - * able to take the signal. + * Post a pending signal to an LWP. Returns non-zero if the LWP may + * be able to take the signal. */ -int -sigpost(struct lwp *l, sig_t action, int prop, int sig) +static int +sigpost(struct lwp *l, sig_t action, int prop, int sig, int idlecheck) { int rv, masked; + struct proc *p = l->l_proc; - KASSERT(mutex_owned(l->l_proc->p_lock)); + KASSERT(mutex_owned(p->p_lock)); /* * If the LWP is on the way out, sigclear() will be busy draining all @@ -1006,18 +1051,32 @@ sigpost(struct lwp *l, sig_t action, int if (l->l_refcnt == 0) return 0; - lwp_lock(l); - /* * Have the LWP check for signals. This ensures that even if no LWP * is found to take the signal immediately, it should be taken soon. */ + lwp_lock(l); l->l_flag |= LW_PENDSIG; /* - * SIGCONT can be masked, but must always restart stopped LWPs. + * When sending signals to SA processes, we first try to find an + * idle VP to take it. + */ + if (idlecheck && (l->l_flag & (LW_SA_IDLE | LW_SA_YIELD)) == 0) { + lwp_unlock(l); + return 0; + } + + /* + * SIGCONT can be masked, but if LWP is stopped, it needs restart. + * Note: SIGKILL and SIGSTOP cannot be masked. */ - masked = sigismember(&l->l_sigmask, sig); +#if KERN_SA + if (p->p_sa != NULL) + masked = sigismember(&p->p_sa->sa_sigmask, sig); + else +#endif + masked = sigismember(&l->l_sigmask, sig); if (masked && ((prop & SA_CONT) == 0 || l->l_stat != LSSTOP)) { lwp_unlock(l); return 0; @@ -1076,7 +1135,7 @@ sigpost(struct lwp *l, sig_t action, int if ((prop & SA_CONT) != 0) { if (l->l_wchan != NULL) { l->l_stat = LSSLEEP; - l->l_proc->p_nrlwps++; + p->p_nrlwps++; rv = 1; break; } @@ -1114,7 +1173,7 @@ signotify(struct lwp *l) * Find an LWP within process p that is waiting on signal ksi, and hand * it on. */ -int +static int sigunwait(struct proc *p, const ksiginfo_t *ksi) { struct lwp *l; @@ -1178,6 +1237,9 @@ kpsignal2(struct proc *p, ksiginfo_t *ks ksiginfo_t *kp; ksiginfoq_t kq; sig_t action; +#ifdef KERN_SA + struct sadata_vp *vp; +#endif KASSERT(!cpu_intr_p()); KASSERT(mutex_owned(proc_lock)); @@ -1306,13 +1368,14 @@ kpsignal2(struct proc *p, ksiginfo_t *ks if (l != NULL) { sigput(&l->l_sigpend, p, kp); membar_producer(); - (void)sigpost(l, action, prop, kp->ksi_signo); + (void)sigpost(l, action, prop, kp->ksi_signo, 0); } goto out; } /* - * Some signals go to all LWPs, even if posted with _lwp_kill(). + * Some signals go to all LWPs, even if posted with _lwp_kill() + * or for an SA process. */ if (p->p_stat == SACTIVE && (p->p_sflag & PS_STOPPING) == 0) { if ((p->p_slflag & PSL_TRACED) != 0) @@ -1325,8 +1388,6 @@ kpsignal2(struct proc *p, ksiginfo_t *ks */ if ((prop & SA_CONT) != 0 && action == SIG_DFL) goto out; - - sigput(&p->p_sigpend, p, kp); } else { /* * Process is stopped or stopping. If traced, then no @@ -1335,7 +1396,10 @@ kpsignal2(struct proc *p, ksiginfo_t *ks if ((p->p_slflag & PSL_TRACED) != 0 && signo != SIGKILL) goto out; - if ((prop & (SA_CONT | SA_KILL)) != 0) { + /* + * Run the process only if sending SIGCONT or SIGKILL. + */ + if ((prop & SA_CONT) != 0 || signo == SIGKILL) { /* * Re-adjust p_nstopchild if the process wasn't * collected by its parent. @@ -1346,27 +1410,28 @@ kpsignal2(struct proc *p, ksiginfo_t *ks p->p_pptr->p_nstopchild--; /* - * If SIGCONT is default (or ignored), we continue - * the process but don't leave the signal in - * ps_siglist, as it has no further action. If - * SIGCONT is held, we continue the process and - * leave the signal in ps_siglist. If the process - * catches SIGCONT, let it handle the signal itself. - * If it isn't waiting on an event, then it goes - * back to run state. Otherwise, process goes back - * to sleep state. + * Do not make signal pending if SIGCONT is default. + * + * If the process catches SIGCONT, let it handle the + * signal itself (if waiting on event - process runs, + * otherwise continues sleeping). */ - if ((prop & SA_CONT) == 0 || action != SIG_DFL) - sigput(&p->p_sigpend, p, kp); + if ((prop & SA_CONT) != 0 && action == SIG_DFL) { + KASSERT(signo != SIGKILL); + goto deliver; + } } else if ((prop & SA_STOP) != 0) { /* * Already stopped, don't need to stop again. * (If we did the shell could get confused.) */ goto out; - } else - sigput(&p->p_sigpend, p, kp); + } } + /* + * Make signal pending. + */ + sigput(&p->p_sigpend, p, kp); deliver: /* @@ -1379,9 +1444,39 @@ kpsignal2(struct proc *p, ksiginfo_t *ks /* * Try to find an LWP that can take the signal. */ - LIST_FOREACH(l, &p->p_lwps, l_sibling) - if (sigpost(l, action, prop, kp->ksi_signo) && !toall) - break; +#if KERN_SA + if ((p->p_sa != NULL) && !toall) { + /* + * If we're in this delivery path, we are delivering a + * signal that needs to go to one thread in the process. + * + * In the SA case, we try to find an idle LWP that can take + * the signal. If that fails, only then do we consider + * interrupting active LWPs. Since the signal's going to + * just one thread, we need only look at "blessed" lwps, + * so scan the vps for them. + */ + l = NULL; + SLIST_FOREACH(vp, &p->p_sa->sa_vps, savp_next) { + l = vp->savp_lwp; + if (sigpost(l, action, prop, kp->ksi_signo, 1)) + break; + } + + if (l == NULL) { + SLIST_FOREACH(vp, &p->p_sa->sa_vps, savp_next) { + l = vp->savp_lwp; + if (sigpost(l, action, prop, kp->ksi_signo, 0)) + break; + } + } + } else /* Catch the brace below if we're defined */ +#endif /* KERN_SA */ + { + LIST_FOREACH(l, &p->p_lwps, l_sibling) + if (sigpost(l, action, prop, kp->ksi_signo, 0) && !toall) + break; + } out: /* @@ -1395,9 +1490,58 @@ void kpsendsig(struct lwp *l, const ksiginfo_t *ksi, const sigset_t *mask) { struct proc *p = l->l_proc; +#ifdef KERN_SA + struct lwp *le, *li; + siginfo_t *si; + int f; +#endif /* KERN_SA */ KASSERT(mutex_owned(p->p_lock)); +#ifdef KERN_SA + if (p->p_sflag & PS_SA) { + /* f indicates if we should clear LP_SA_NOBLOCK */ + f = ~l->l_pflag & LP_SA_NOBLOCK; + l->l_pflag |= LP_SA_NOBLOCK; + + mutex_exit(p->p_lock); + /* XXXUPSXXX What if not on sa_vp? */ + /* + * WRS: I think it won't matter, beyond the + * question of what exactly we do with a signal + * to a blocked user thread. Also, we try hard to always + * send signals to blessed lwps, so we would only send + * to a non-blessed lwp under special circumstances. + */ + si = siginfo_alloc(PR_WAITOK); + + si->_info = ksi->ksi_info; + + /* + * Figure out if we're the innocent victim or the main + * perpitrator. + */ + le = li = NULL; + if (KSI_TRAP_P(ksi)) + le = l; + else + li = l; + if (sa_upcall(l, SA_UPCALL_SIGNAL | SA_UPCALL_DEFER, le, li, + sizeof(*si), si, siginfo_free) != 0) { + siginfo_free(si); +#if 0 + if (KSI_TRAP_P(ksi)) + /* XXX What dowe do here? The signal + * didn't make it + */; +#endif + } + l->l_pflag ^= f; + mutex_enter(p->p_lock); + return; + } +#endif /* KERN_SA */ + (*p->p_emul->e_sendsig)(ksi, mask); } @@ -1452,14 +1596,12 @@ proc_stop_done(struct proc *p, bool ppsi /* * Stop the current process and switch away when being stopped or traced. */ -void +static void sigswitch(bool ppsig, int ppmask, int signo) { struct lwp *l = curlwp; struct proc *p = l->l_proc; -#ifdef MULTIPROCESSOR int biglocks; -#endif KASSERT(mutex_owned(p->p_lock)); KASSERT(l->l_stat == LSONPROC); @@ -1520,15 +1662,20 @@ sigswitch(bool ppsig, int ppmask, int si /* * Check for a signal from the debugger. */ -int -sigchecktrace(sigpend_t **spp) +static int +sigchecktrace(void) { struct lwp *l = curlwp; struct proc *p = l->l_proc; + sigset_t *mask; int signo; KASSERT(mutex_owned(p->p_lock)); + /* If there's a pending SIGKILL, process it immediately. */ + if (sigismember(&p->p_sigpend.sp_set, SIGKILL)) + return 0; + /* * If we are no longer being traced, or the parent didn't * give us a signal, look for more signals. @@ -1536,21 +1683,14 @@ sigchecktrace(sigpend_t **spp) if ((p->p_slflag & PSL_TRACED) == 0 || p->p_xstat == 0) return 0; - /* If there's a pending SIGKILL, process it immediately. */ - if (sigismember(&p->p_sigpend.sp_set, SIGKILL)) - return 0; - /* * If the new signal is being masked, look for other signals. * `p->p_sigctx.ps_siglist |= mask' is done in setrunnable(). */ signo = p->p_xstat; p->p_xstat = 0; - if ((sigprop[signo] & SA_TOLWP) != 0) - *spp = &l->l_sigpend; - else - *spp = &p->p_sigpend; - if (sigismember(&l->l_sigmask, signo)) + mask = (p->p_sa != NULL) ? &p->p_sa->sa_sigmask : &l->l_sigmask; + if (sigismember(mask, signo)) signo = 0; return signo; @@ -1566,18 +1706,20 @@ sigchecktrace(sigpend_t **spp) * * We will also return -1 if the process is exiting and the current LWP must * follow suit. - * - * Note that we may be called while on a sleep queue, so MUST NOT sleep. We - * can switch away, though. */ int issignal(struct lwp *l) { - struct proc *p = l->l_proc; - int signo = 0, prop; - sigpend_t *sp = NULL; + struct proc *p; + int signo, prop; + sigpend_t *sp; sigset_t ss; + p = l->l_proc; + sp = NULL; + signo = 0; + + KASSERT(p == curproc); KASSERT(mutex_owned(p->p_lock)); for (;;) { @@ -1585,6 +1727,10 @@ issignal(struct lwp *l) if (signo != 0) (void)sigget(sp, NULL, signo, NULL); + /* Bail out if we do not own the virtual processor */ + if (l->l_flag & LW_SA && l->l_savp->savp_lwp != l) + break; + /* * If the process is stopped/stopping, then stop ourselves * now that we're on the kernel/userspace boundary. When @@ -1592,10 +1738,13 @@ issignal(struct lwp *l) */ if (p->p_stat == SSTOP || (p->p_sflag & PS_STOPPING) != 0) { sigswitch(true, PS_NOCLDSTOP, 0); - signo = sigchecktrace(&sp); + signo = sigchecktrace(); } else signo = 0; + /* Signals from the debugger are "out of band". */ + sp = NULL; + /* * If the debugger didn't provide a signal, find a pending * signal from our set. Check per-LWP signals first, and @@ -1604,14 +1753,14 @@ issignal(struct lwp *l) if (signo == 0) { sp = &l->l_sigpend; ss = sp->sp_set; - if ((p->p_sflag & PS_PPWAIT) != 0) + if ((p->p_lflag & PL_PPWAIT) != 0) sigminusset(&stopsigmask, &ss); sigminusset(&l->l_sigmask, &ss); if ((signo = firstsig(&ss)) == 0) { sp = &p->p_sigpend; ss = sp->sp_set; - if ((p->p_sflag & PS_PPWAIT) != 0) + if ((p->p_lflag & PL_PPWAIT) != 0) sigminusset(&stopsigmask, &ss); sigminusset(&l->l_sigmask, &ss); @@ -1645,7 +1794,7 @@ issignal(struct lwp *l) * for us, don't hang as we could deadlock. */ if ((p->p_slflag & PSL_TRACED) != 0 && - (p->p_sflag & PS_PPWAIT) == 0 && signo != SIGKILL) { + (p->p_lflag & PL_PPWAIT) == 0 && signo != SIGKILL) { /* Take the signal. */ (void)sigget(sp, NULL, signo, NULL); p->p_xstat = signo; @@ -1657,8 +1806,11 @@ issignal(struct lwp *l) signo); /* Check for a signal from the debugger. */ - if ((signo = sigchecktrace(&sp)) == 0) + if ((signo = sigchecktrace()) == 0) continue; + + /* Signals from the debugger are "out of band". */ + sp = NULL; } prop = sigprop[signo]; @@ -1768,7 +1920,7 @@ postsig(int signo) * signal. * * Special case: user has done a sigsuspend. Here the current mask is - * not of interest, but rather the mask from before the sigsuspen is + * not of interest, but rather the mask from before the sigsuspend is * what we want restored after the signal processing is completed. */ if (l->l_sigrestore) { @@ -1786,7 +1938,7 @@ postsig(int signo) if (ktrpoint(KTR_PSIG)) { mutex_exit(p->p_lock); - ktrpsig(signo, action, returnmask, NULL); + ktrpsig(signo, action, returnmask, &ksi); mutex_enter(p->p_lock); } @@ -1811,6 +1963,41 @@ postsig(int signo) } /* + * sendsig: + * + * Default signal delivery method for NetBSD. + */ +void +sendsig(const struct ksiginfo *ksi, const sigset_t *mask) +{ + struct sigacts *sa; + int sig; + + sig = ksi->ksi_signo; + sa = curproc->p_sigacts; + + switch (sa->sa_sigdesc[sig].sd_vers) { + case 0: + case 1: + /* Compat for 1.6 and earlier. */ + if (sendsig_sigcontext_vec == NULL) { + break; + } + (*sendsig_sigcontext_vec)(ksi, mask); + return; + case 2: + case 3: + sendsig_siginfo(ksi, mask); + return; + default: + break; + } + + printf("sendsig: bad version %d\n", sa->sa_sigdesc[sig].sd_vers); + sigexit(curlwp, SIGILL); +} + +/* * sendsig_reset: * * Reset the signal action. Called from emulation specific sendsig() @@ -1821,6 +2008,7 @@ sendsig_reset(struct lwp *l, int signo) { struct proc *p = l->l_proc; struct sigacts *ps = p->p_sigacts; + sigset_t *mask; KASSERT(mutex_owned(p->p_lock)); @@ -1828,8 +2016,10 @@ sendsig_reset(struct lwp *l, int signo) p->p_sigctx.ps_code = 0; p->p_sigctx.ps_signo = 0; + mask = (p->p_sa != NULL) ? &p->p_sa->sa_sigmask : &l->l_sigmask; + mutex_enter(&ps->sa_mutex); - sigplusset(&SIGACTION_PS(ps, signo).sa_mask, &l->l_sigmask); + sigplusset(&SIGACTION_PS(ps, signo).sa_mask, mask); if (SIGACTION_PS(ps, signo).sa_flags & SA_RESETHAND) { sigdelset(&p->p_sigctx.ps_sigcatch, signo); if (signo != SIGCONT && sigprop[signo] & SA_IGNORE) @@ -1935,7 +2125,7 @@ sigexit(struct lwp *l, int signo) if (docore) { mutex_exit(p->p_lock); - if ((error = coredump(l, NULL)) == 0) + if ((error = (*coredump_vec)(l, NULL)) == 0) exitsig |= WCOREFLAG; if (kern_logsigexit) { @@ -2002,7 +2192,7 @@ proc_stop(struct proc *p, int notify, in * proc_stop_callout() to ensure that they do. */ LIST_FOREACH(l, &p->p_lwps, l_sibling) - sigpost(l, SIG_DFL, SA_STOP, signo); + sigpost(l, SIG_DFL, SA_STOP, signo, 0); callout_schedule(&proc_stop_ch, 1); } }