diff --git a/sys/alpha/alpha/machdep.c b/sys/alpha/alpha/machdep.c index 1efc6b9eedb9..c9b2caf13d39 100644 --- a/sys/alpha/alpha/machdep.c +++ b/sys/alpha/alpha/machdep.c @@ -1133,11 +1133,13 @@ osendsig(sig_t catcher, int sig, sigset_t *mask, u_long code) td = curthread; p = td->td_proc; PROC_LOCK_ASSERT(p, MA_OWNED); + psp = p->p_sigacts; + mtx_assert(&psp->ps_mtx, MA_OWNED); + frame = td->td_frame; - oonstack = sigonstack(alpha_pal_rdusp()); fsize = sizeof ksi; rndfsize = ((fsize + 15) / 16) * 16; - psp = p->p_sigacts; + oonstack = sigonstack(alpha_pal_rdusp()); /* * Allocate and validate space for the signal handler @@ -1155,6 +1157,7 @@ osendsig(sig_t catcher, int sig, sigset_t *mask, u_long code) #endif } else sip = (osiginfo_t *)(alpha_pal_rdusp() - rndfsize); + mtx_unlock(&psp->ps_mtx); PROC_UNLOCK(p); /* @@ -1210,7 +1213,8 @@ osendsig(sig_t catcher, int sig, sigset_t *mask, u_long code) frame->tf_regs[FRAME_A0] = sig; frame->tf_regs[FRAME_FLAGS] = 0; /* full restore */ PROC_LOCK(p); - if (SIGISMEMBER(p->p_sigacts->ps_siginfo, sig)) + mtx_lock(&psp->ps_mtx); + if (SIGISMEMBER(psp->ps_siginfo, sig)) frame->tf_regs[FRAME_A1] = (u_int64_t)sip; else frame->tf_regs[FRAME_A1] = code; @@ -1235,6 +1239,7 @@ freebsd4_sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code) p = td->td_proc; PROC_LOCK_ASSERT(p, MA_OWNED); psp = p->p_sigacts; + mtx_assert(&psp->ps_mtx, MA_OWNED); frame = td->td_frame; oonstack = sigonstack(alpha_pal_rdusp()); @@ -1276,6 +1281,7 @@ freebsd4_sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code) #endif } else sfp = (struct sigframe4 *)(alpha_pal_rdusp() - rndfsize); + mtx_unlock(&psp->ps_mtx); PROC_UNLOCK(p); /* save the floating-point state, if necessary, then copy it. */ @@ -1311,7 +1317,8 @@ freebsd4_sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code) frame->tf_regs[FRAME_PC] = PS_STRINGS - szfreebsd4_sigcode; frame->tf_regs[FRAME_A0] = sig; PROC_LOCK(p); - if (SIGISMEMBER(p->p_sigacts->ps_siginfo, sig)) { + mtx_lock(&psp->ps_mtx); + if (SIGISMEMBER(psp->ps_siginfo, sig)) { frame->tf_regs[FRAME_A1] = (u_int64_t)&(sfp->sf_si); /* Fill in POSIX parts */ @@ -1343,6 +1350,7 @@ sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code) p = td->td_proc; PROC_LOCK_ASSERT(p, MA_OWNED); psp = p->p_sigacts; + mtx_assert(&psp->ps_mtx, MA_OWNED); #ifdef COMPAT_FREEBSD4 if (SIGISMEMBER(psp->ps_freebsd4, sig)) { freebsd4_sendsig(catcher, sig, mask, code); @@ -1397,6 +1405,7 @@ sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code) #endif } else sfp = (struct sigframe *)(alpha_pal_rdusp() - rndfsize); + mtx_unlock(&psp->ps_mtx); PROC_UNLOCK(p); /* save the floating-point state, if necessary, then copy it. */ @@ -1432,7 +1441,8 @@ sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code) frame->tf_regs[FRAME_PC] = PS_STRINGS - szsigcode; frame->tf_regs[FRAME_A0] = sig; PROC_LOCK(p); - if (SIGISMEMBER(p->p_sigacts->ps_siginfo, sig)) { + mtx_lock(&psp->ps_mtx); + if (SIGISMEMBER(psp->ps_siginfo, sig)) { frame->tf_regs[FRAME_A1] = (u_int64_t)&(sfp->sf_si); /* Fill in POSIX parts */ diff --git a/sys/alpha/osf1/osf1_signal.c b/sys/alpha/osf1/osf1_signal.c index bc3e06c9d95d..4ba7e86f849e 100644 --- a/sys/alpha/osf1/osf1_signal.c +++ b/sys/alpha/osf1/osf1_signal.c @@ -471,6 +471,7 @@ osf1_sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code) p = td->td_proc; PROC_LOCK_ASSERT(p, MA_OWNED); psp = p->p_sigacts; + mtx_assert(&psp->ps_mtx, MA_OWNED); frame = td->td_frame; oonstack = sigonstack(alpha_pal_rdusp()); @@ -490,6 +491,7 @@ osf1_sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code) p->p_sigstk.ss_flags |= SS_ONSTACK; } else sip = (osiginfo_t *)(alpha_pal_rdusp() - rndfsize); + mtx_unlock(&psp->ps_mtx); PROC_UNLOCK(p); /* @@ -551,6 +553,7 @@ osf1_sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code) frame->tf_regs[FRAME_FLAGS] = 0; /* full restore */ alpha_pal_wrusp((unsigned long)sip); PROC_LOCK(p); + mtx_lock(&psp->ps_mtx); } diff --git a/sys/amd64/amd64/machdep.c b/sys/amd64/amd64/machdep.c index cafc80bb1fa7..b72725665192 100644 --- a/sys/amd64/amd64/machdep.c +++ b/sys/amd64/amd64/machdep.c @@ -235,6 +235,7 @@ sendsig(catcher, sig, mask, code) p = td->td_proc; PROC_LOCK_ASSERT(p, MA_OWNED); psp = p->p_sigacts; + mtx_assert(&psp->ps_mtx, MA_OWNED); regs = td->td_frame; oonstack = sigonstack(regs->tf_rsp); @@ -262,7 +263,6 @@ sendsig(catcher, sig, mask, code) sp = (char *)regs->tf_rsp - sizeof(struct sigframe) - 128; /* Align to 16 bytes. */ sfp = (struct sigframe *)((unsigned long)sp & ~0xF); - PROC_UNLOCK(p); /* Translate the signal if appropriate. */ if (p->p_sysent->sv_sigtbl && sig <= p->p_sysent->sv_sigsize) @@ -271,8 +271,7 @@ sendsig(catcher, sig, mask, code) /* Build the argument list for the signal handler. */ regs->tf_rdi = sig; /* arg 1 in %rdi */ regs->tf_rdx = (register_t)&sfp->sf_uc; /* arg 3 in %rdx */ - PROC_LOCK(p); - if (SIGISMEMBER(p->p_sigacts->ps_siginfo, sig)) { + if (SIGISMEMBER(psp->ps_siginfo, sig)) { /* Signal handler installed with SA_SIGINFO. */ regs->tf_rsi = (register_t)&sfp->sf_si; /* arg 2 in %rsi */ sf.sf_ahu.sf_action = (__siginfohandler_t *)catcher; @@ -287,6 +286,7 @@ sendsig(catcher, sig, mask, code) regs->tf_rcx = regs->tf_addr; /* arg 4 in %rcx */ sf.sf_ahu.sf_handler = catcher; } + mtx_unlock(&psp->ps_mtx); PROC_UNLOCK(p); /* @@ -305,6 +305,7 @@ sendsig(catcher, sig, mask, code) regs->tf_rflags &= ~PSL_T; regs->tf_cs = _ucodesel; PROC_LOCK(p); + mtx_lock(&psp->ps_mtx); } /* diff --git a/sys/compat/linprocfs/linprocfs.c b/sys/compat/linprocfs/linprocfs.c index 033346ba694d..14f9aebdd02e 100644 --- a/sys/compat/linprocfs/linprocfs.c +++ b/sys/compat/linprocfs/linprocfs.c @@ -547,6 +547,7 @@ linprocfs_doprocstatus(PFS_FILL_ARGS) char *state; segsz_t lsize; struct thread *td2; + struct sigacts *ps; int i; PROC_LOCK(p); @@ -653,8 +654,11 @@ linprocfs_doprocstatus(PFS_FILL_ARGS) * relation to struct proc, so SigBlk is left unimplemented. */ sbuf_printf(sb, "SigBlk:\t%08x\n", 0); /* XXX */ - sbuf_printf(sb, "SigIgn:\t%08x\n", p->p_sigignore.__bits[0]); - sbuf_printf(sb, "SigCgt:\t%08x\n", p->p_sigcatch.__bits[0]); + ps = p->p_sigacts; + mtx_lock(&ps->ps_mtx); + sbuf_printf(sb, "SigIgn:\t%08x\n", ps->ps_sigignore.__bits[0]); + sbuf_printf(sb, "SigCgt:\t%08x\n", ps->ps_sigcatch.__bits[0]); + mtx_unlock(&ps->ps_mtx); PROC_UNLOCK(p); /* diff --git a/sys/compat/svr4/svr4_filio.c b/sys/compat/svr4/svr4_filio.c index 870da5d0427e..374338f46c7f 100644 --- a/sys/compat/svr4/svr4_filio.c +++ b/sys/compat/svr4/svr4_filio.c @@ -132,10 +132,21 @@ svr4_sys_read(td, uap) DPRINTF(("svr4_read(%d, 0x%0x, %d) = %d\n", uap->fd, uap->buf, uap->nbyte, rv)); if (rv == EAGAIN) { +#ifdef DEBUG_SVR4 + struct sigacts *ps; + + PROC_LOCK(td->td_proc); + ps = td->td_proc->p_sigacts; + mtx_lock(&ps->ps_mtx); +#endif DPRINTF(("sigmask = 0x%x\n", td->td_sigmask)); - DPRINTF(("sigignore = 0x%x\n", td->td_proc->p_sigignore)); - DPRINTF(("sigcaught = 0x%x\n", td->td_proc->p_sigcatch)); + DPRINTF(("sigignore = 0x%x\n", ps->ps_sigignore)); + DPRINTF(("sigcaught = 0x%x\n", ps->ps_sigcatch)); DPRINTF(("siglist = 0x%x\n", td->td_siglist)); +#ifdef DEBUG_SVR4 + mtx_unlock(&ps->ps_mtx); + PROC_UNLOCK(td->td_proc); +#endif } #if defined(GROTTY_READ_HACK) diff --git a/sys/compat/svr4/svr4_misc.c b/sys/compat/svr4/svr4_misc.c index 81eef6656b1b..22fdc66138cf 100644 --- a/sys/compat/svr4/svr4_misc.c +++ b/sys/compat/svr4/svr4_misc.c @@ -1363,12 +1363,8 @@ loop: sx_xunlock(&proctree_lock); PROC_LOCK(q); - if (--q->p_procsig->ps_refcnt == 0) { - if (q->p_sigacts != &q->p_uarea->u_sigacts) - FREE(q->p_sigacts, M_SUBPROC); - FREE(q->p_procsig, M_SUBPROC); - q->p_procsig = NULL; - } + sigacts_free(q->p_sigacts); + q->p_sigacts = NULL; PROC_UNLOCK(q); /* diff --git a/sys/i386/i386/machdep.c b/sys/i386/i386/machdep.c index e5377d4477e6..912035d9ad54 100644 --- a/sys/i386/i386/machdep.c +++ b/sys/i386/i386/machdep.c @@ -295,6 +295,7 @@ osendsig(catcher, sig, mask, code) p = td->td_proc; PROC_LOCK_ASSERT(p, MA_OWNED); psp = p->p_sigacts; + mtx_assert(&psp->ps_mtx, MA_OWNED); regs = td->td_frame; oonstack = sigonstack(regs->tf_esp); @@ -308,7 +309,6 @@ osendsig(catcher, sig, mask, code) #endif } else fp = (struct osigframe *)regs->tf_esp - 1; - PROC_UNLOCK(p); /* Translate the signal if appropriate. */ if (p->p_sysent->sv_sigtbl && sig <= p->p_sysent->sv_sigsize) @@ -317,8 +317,7 @@ osendsig(catcher, sig, mask, code) /* Build the argument list for the signal handler. */ sf.sf_signum = sig; sf.sf_scp = (register_t)&fp->sf_siginfo.si_sc; - PROC_LOCK(p); - if (SIGISMEMBER(p->p_sigacts->ps_siginfo, sig)) { + if (SIGISMEMBER(psp->ps_siginfo, sig)) { /* Signal handler installed with SA_SIGINFO. */ sf.sf_arg2 = (register_t)&fp->sf_siginfo; sf.sf_siginfo.si_signo = sig; @@ -330,6 +329,7 @@ osendsig(catcher, sig, mask, code) sf.sf_addr = regs->tf_err; sf.sf_ahu.sf_handler = catcher; } + mtx_unlock(&psp->ps_mtx); PROC_UNLOCK(p); /* Save most if not all of trap frame. */ @@ -402,6 +402,7 @@ osendsig(catcher, sig, mask, code) load_gs(_udatasel); regs->tf_ss = _udatasel; PROC_LOCK(p); + mtx_lock(&psp->ps_mtx); } #endif /* COMPAT_43 */ @@ -424,6 +425,7 @@ freebsd4_sendsig(catcher, sig, mask, code) p = td->td_proc; PROC_LOCK_ASSERT(p, MA_OWNED); psp = p->p_sigacts; + mtx_assert(&psp->ps_mtx, MA_OWNED); regs = td->td_frame; oonstack = sigonstack(regs->tf_esp); @@ -447,7 +449,6 @@ freebsd4_sendsig(catcher, sig, mask, code) #endif } else sfp = (struct sigframe4 *)regs->tf_esp - 1; - PROC_UNLOCK(p); /* Translate the signal if appropriate. */ if (p->p_sysent->sv_sigtbl && sig <= p->p_sysent->sv_sigsize) @@ -456,8 +457,7 @@ freebsd4_sendsig(catcher, sig, mask, code) /* Build the argument list for the signal handler. */ sf.sf_signum = sig; sf.sf_ucontext = (register_t)&sfp->sf_uc; - PROC_LOCK(p); - if (SIGISMEMBER(p->p_sigacts->ps_siginfo, sig)) { + if (SIGISMEMBER(psp->ps_siginfo, sig)) { /* Signal handler installed with SA_SIGINFO. */ sf.sf_siginfo = (register_t)&sfp->sf_si; sf.sf_ahu.sf_action = (__siginfohandler_t *)catcher; @@ -472,6 +472,7 @@ freebsd4_sendsig(catcher, sig, mask, code) sf.sf_addr = regs->tf_err; sf.sf_ahu.sf_handler = catcher; } + mtx_unlock(&psp->ps_mtx); PROC_UNLOCK(p); /* @@ -523,6 +524,7 @@ freebsd4_sendsig(catcher, sig, mask, code) regs->tf_fs = _udatasel; regs->tf_ss = _udatasel; PROC_LOCK(p); + mtx_lock(&psp->ps_mtx); } #endif /* COMPAT_FREEBSD4 */ @@ -545,6 +547,7 @@ sendsig(catcher, sig, mask, code) p = td->td_proc; PROC_LOCK_ASSERT(p, MA_OWNED); psp = p->p_sigacts; + mtx_assert(&psp->ps_mtx, MA_OWNED); #ifdef COMPAT_FREEBSD4 if (SIGISMEMBER(psp->ps_freebsd4, sig)) { freebsd4_sendsig(catcher, sig, mask, code); @@ -585,7 +588,6 @@ sendsig(catcher, sig, mask, code) sp = (char *)regs->tf_esp - sizeof(struct sigframe); /* Align to 16 bytes. */ sfp = (struct sigframe *)((unsigned int)sp & ~0xF); - PROC_UNLOCK(p); /* Translate the signal if appropriate. */ if (p->p_sysent->sv_sigtbl && sig <= p->p_sysent->sv_sigsize) @@ -594,8 +596,7 @@ sendsig(catcher, sig, mask, code) /* Build the argument list for the signal handler. */ sf.sf_signum = sig; sf.sf_ucontext = (register_t)&sfp->sf_uc; - PROC_LOCK(p); - if (SIGISMEMBER(p->p_sigacts->ps_siginfo, sig)) { + if (SIGISMEMBER(psp->ps_siginfo, sig)) { /* Signal handler installed with SA_SIGINFO. */ sf.sf_siginfo = (register_t)&sfp->sf_si; sf.sf_ahu.sf_action = (__siginfohandler_t *)catcher; @@ -610,6 +611,7 @@ sendsig(catcher, sig, mask, code) sf.sf_addr = regs->tf_err; sf.sf_ahu.sf_handler = catcher; } + mtx_unlock(&psp->ps_mtx); PROC_UNLOCK(p); /* @@ -661,6 +663,7 @@ sendsig(catcher, sig, mask, code) regs->tf_fs = _udatasel; regs->tf_ss = _udatasel; PROC_LOCK(p); + mtx_lock(&psp->ps_mtx); } /* diff --git a/sys/i386/linux/linux_sysvec.c b/sys/i386/linux/linux_sysvec.c index 27105bc71b5d..706c944d51c0 100644 --- a/sys/i386/linux/linux_sysvec.c +++ b/sys/i386/linux/linux_sysvec.c @@ -273,11 +273,14 @@ linux_rt_sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code) { struct thread *td = curthread; struct proc *p = td->td_proc; + struct sigacts *psp; struct trapframe *regs; struct l_rt_sigframe *fp, frame; int oonstack; PROC_LOCK_ASSERT(p, MA_OWNED); + psp = p->p_sigacts; + mtx_assert(&psp->ps_mtx, MA_OWNED); regs = td->td_frame; oonstack = sigonstack(regs->tf_esp); @@ -290,11 +293,12 @@ linux_rt_sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code) * Allocate space for the signal handler context. */ if ((p->p_flag & P_ALTSTACK) && !oonstack && - SIGISMEMBER(p->p_sigacts->ps_sigonstack, sig)) { + SIGISMEMBER(psp->ps_sigonstack, sig)) { fp = (struct l_rt_sigframe *)(p->p_sigstk.ss_sp + p->p_sigstk.ss_size - sizeof(struct l_rt_sigframe)); } else fp = (struct l_rt_sigframe *)regs->tf_esp - 1; + mtx_unlock(&psp->ps_mtx); /* * Build the argument list for the signal handler. @@ -383,6 +387,7 @@ linux_rt_sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code) regs->tf_fs = _udatasel; regs->tf_ss = _udatasel; PROC_LOCK(p); + mtx_lock(&psp->ps_mtx); } @@ -401,13 +406,16 @@ linux_sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code) { struct thread *td = curthread; struct proc *p = td->td_proc; + struct sigacts *psp; struct trapframe *regs; struct l_sigframe *fp, frame; l_sigset_t lmask; int oonstack, i; PROC_LOCK_ASSERT(p, MA_OWNED); - if (SIGISMEMBER(p->p_sigacts->ps_siginfo, sig)) { + psp = p->p_sigacts; + mtx_assert(&psp->ps_mtx, MA_OWNED); + if (SIGISMEMBER(psp->ps_siginfo, sig)) { /* Signal handler installed with SA_SIGINFO. */ linux_rt_sendsig(catcher, sig, mask, code); return; @@ -426,11 +434,12 @@ linux_sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code) * Allocate space for the signal handler context. */ if ((p->p_flag & P_ALTSTACK) && !oonstack && - SIGISMEMBER(p->p_sigacts->ps_sigonstack, sig)) { + SIGISMEMBER(psp->ps_sigonstack, sig)) { fp = (struct l_sigframe *)(p->p_sigstk.ss_sp + p->p_sigstk.ss_size - sizeof(struct l_sigframe)); } else fp = (struct l_sigframe *)regs->tf_esp - 1; + mtx_unlock(&psp->ps_mtx); PROC_UNLOCK(p); /* @@ -494,6 +503,7 @@ linux_sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code) regs->tf_fs = _udatasel; regs->tf_ss = _udatasel; PROC_LOCK(p); + mtx_lock(&psp->ps_mtx); } /* diff --git a/sys/i386/svr4/svr4_machdep.c b/sys/i386/svr4/svr4_machdep.c index d29e37bf45d1..e477629e2c6e 100644 --- a/sys/i386/svr4/svr4_machdep.c +++ b/sys/i386/svr4/svr4_machdep.c @@ -428,6 +428,7 @@ svr4_sendsig(catcher, sig, mask, code) #endif PROC_LOCK_ASSERT(p, MA_OWNED); psp = p->p_sigacts; + mtx_assert(&psp->ps_mtx, MA_OWNED); tf = td->td_frame; oonstack = sigonstack(tf->tf_esp); @@ -443,6 +444,7 @@ svr4_sendsig(catcher, sig, mask, code) } else { fp = (struct svr4_sigframe *)tf->tf_esp - 1; } + mtx_unlock(&psp->ps_mtx); PROC_UNLOCK(p); /* @@ -505,6 +507,7 @@ svr4_sendsig(catcher, sig, mask, code) load_gs(_udatasel); tf->tf_ss = _udatasel; PROC_LOCK(p); + mtx_lock(&psp->ps_mtx); #endif } diff --git a/sys/ia64/ia64/machdep.c b/sys/ia64/ia64/machdep.c index fafe287097b9..dd3fc590f182 100644 --- a/sys/ia64/ia64/machdep.c +++ b/sys/ia64/ia64/machdep.c @@ -756,6 +756,7 @@ sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code) p = td->td_proc; PROC_LOCK_ASSERT(p, MA_OWNED); psp = p->p_sigacts; + mtx_assert(&psp->ps_mtx, MA_OWNED); frame = td->td_frame; oonstack = sigonstack(frame->tf_r[FRAME_SP]); rndfsize = ((sizeof(sf) + 15) / 16) * 16; @@ -822,6 +823,7 @@ sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code) #endif } else sfp = (struct sigframe *)(frame->tf_r[FRAME_SP] - rndfsize); + mtx_unlock(&psp->ps_mtx); PROC_UNLOCK(p); #ifdef DEBUG @@ -870,7 +872,8 @@ sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code) frame->tf_cr_iip = PS_STRINGS - (esigcode - sigcode); frame->tf_r[FRAME_R1] = sig; PROC_LOCK(p); - if (SIGISMEMBER(p->p_sigacts->ps_siginfo, sig)) { + mtx_lock(&psp->ps_mtx); + if (SIGISMEMBER(psp->ps_siginfo, sig)) { frame->tf_r[FRAME_R15] = (u_int64_t)&(sfp->sf_si); /* Fill in POSIX parts */ diff --git a/sys/kern/init_main.c b/sys/kern/init_main.c index 83fca78c4ede..6caec77bec39 100644 --- a/sys/kern/init_main.c +++ b/sys/kern/init_main.c @@ -90,7 +90,6 @@ struct proc proc0; struct thread thread0; struct kse kse0; struct ksegrp ksegrp0; -static struct procsig procsig0; static struct filedesc0 filedesc0; static struct plimit limit0; struct vmspace vmspace0; @@ -399,9 +398,8 @@ proc0_init(void *dummy __unused) #endif td->td_ucred = crhold(p->p_ucred); - /* Create procsig. */ - p->p_procsig = &procsig0; - p->p_procsig->ps_refcnt = 1; + /* Create sigacts. */ + p->p_sigacts = sigacts_alloc(); /* Initialize signal state for process 0. */ siginit(&proc0); @@ -441,11 +439,10 @@ proc0_init(void *dummy __unused) vmspace0.vm_map.pmap = vmspace_pmap(&vmspace0); /* - * We continue to place resource usage info and signal - * actions in the user struct so they're pageable. + * We continue to place resource usage info + * in the user struct so that it's pageable. */ p->p_stats = &p->p_uarea->u_stats; - p->p_sigacts = &p->p_uarea->u_sigacts; /* * Charge root for one process. diff --git a/sys/kern/kern_condvar.c b/sys/kern/kern_condvar.c index 160434b041fe..7852234f8c26 100644 --- a/sys/kern/kern_condvar.c +++ b/sys/kern/kern_condvar.c @@ -146,7 +146,9 @@ cv_switch_catch(struct thread *td) mtx_unlock_spin(&sched_lock); p = td->td_proc; PROC_LOCK(p); + mtx_lock(&p->p_sigacts->ps_mtx); sig = cursig(td); + mtx_unlock(&p->p_sigacts->ps_mtx); if (thread_suspend_check(1)) sig = SIGSTOP; mtx_lock_spin(&sched_lock); @@ -283,6 +285,7 @@ cv_wait_sig(struct cv *cvp, struct mtx *mp) mtx_unlock_spin(&sched_lock); PROC_LOCK(p); + mtx_lock(&p->p_sigacts->ps_mtx); if (sig == 0) sig = cursig(td); /* XXXKSE */ if (sig != 0) { @@ -291,6 +294,7 @@ cv_wait_sig(struct cv *cvp, struct mtx *mp) else rval = ERESTART; } + mtx_unlock(&p->p_sigacts->ps_mtx); if (p->p_flag & P_WEXIT) rval = EINTR; PROC_UNLOCK(p); @@ -446,6 +450,7 @@ cv_timedwait_sig(struct cv *cvp, struct mtx *mp, int timo) mtx_unlock_spin(&sched_lock); PROC_LOCK(p); + mtx_lock(&p->p_sigacts->ps_mtx); if (sig == 0) sig = cursig(td); if (sig != 0) { @@ -454,6 +459,7 @@ cv_timedwait_sig(struct cv *cvp, struct mtx *mp, int timo) else rval = ERESTART; } + mtx_unlock(&p->p_sigacts->ps_mtx); if (p->p_flag & P_WEXIT) rval = EINTR; PROC_UNLOCK(p); diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c index 7f5c81938d99..a4531527ec98 100644 --- a/sys/kern/kern_exec.c +++ b/sys/kern/kern_exec.c @@ -163,7 +163,7 @@ kern_execve(td, fname, argv, envv, mac_p) struct vattr attr; int (*img_first)(struct image_params *); struct pargs *oldargs = NULL, *newargs = NULL; - struct procsig *oldprocsig, *newprocsig; + struct sigacts *oldsigacts, *newsigacts; #ifdef KTRACE struct vnode *tracevp = NULL; struct ucred *tracecred = NULL; @@ -409,23 +409,16 @@ interpret: * reset. */ PROC_LOCK(p); - mp_fixme("procsig needs a lock"); - if (p->p_procsig->ps_refcnt > 1) { - oldprocsig = p->p_procsig; + if (sigacts_shared(p->p_sigacts)) { + oldsigacts = p->p_sigacts; PROC_UNLOCK(p); - MALLOC(newprocsig, struct procsig *, sizeof(struct procsig), - M_SUBPROC, M_WAITOK); - bcopy(oldprocsig, newprocsig, sizeof(*newprocsig)); - newprocsig->ps_refcnt = 1; - oldprocsig->ps_refcnt--; + newsigacts = sigacts_alloc(); + sigacts_copy(newsigacts, oldsigacts); PROC_LOCK(p); - p->p_procsig = newprocsig; - if (p->p_sigacts == &p->p_uarea->u_sigacts) - panic("shared procsig but private sigacts?"); + p->p_sigacts = newsigacts; + } else + oldsigacts = NULL; - p->p_uarea->u_sigacts = *p->p_sigacts; - p->p_sigacts = &p->p_uarea->u_sigacts; - } /* Stop profiling */ stopprofclock(p); @@ -624,6 +617,8 @@ done1: pargs_drop(oldargs); if (newargs != NULL) pargs_drop(newargs); + if (oldsigacts != NULL) + sigacts_free(oldsigacts); exec_fail_dealloc: diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c index b77c1d9cc059..2adfa9cf7b9b 100644 --- a/sys/kern/kern_exit.c +++ b/sys/kern/kern_exit.c @@ -431,9 +431,11 @@ exit1(struct thread *td, int rv) * 1 instead (and hope it will handle this situation). */ PROC_LOCK(p->p_pptr); - if (p->p_pptr->p_procsig->ps_flag & (PS_NOCLDWAIT | PS_CLDSIGIGN)) { + mtx_lock(&p->p_pptr->p_sigacts->ps_mtx); + if (p->p_pptr->p_sigacts->ps_flag & (PS_NOCLDWAIT | PS_CLDSIGIGN)) { struct proc *pp; + mtx_unlock(&p->p_pptr->p_sigacts->ps_mtx); pp = p->p_pptr; PROC_UNLOCK(pp); proc_reparent(p, initproc); @@ -445,7 +447,8 @@ exit1(struct thread *td, int rv) */ if (LIST_EMPTY(&pp->p_children)) wakeup(pp); - } + } else + mtx_unlock(&p->p_pptr->p_sigacts->ps_mtx); if (p->p_sigparent && p->p_pptr != initproc) psignal(p->p_pptr, p->p_sigparent); @@ -656,23 +659,14 @@ loop: (void)chgproccnt(p->p_ucred->cr_ruidinfo, -1, 0); /* - * Free up credentials. + * Free credentials, arguments, and sigacts */ crfree(p->p_ucred); - p->p_ucred = NULL; /* XXX: why? */ - - /* - * Remove unused arguments - */ + p->p_ucred = NULL; pargs_drop(p->p_args); p->p_args = NULL; - - if (--p->p_procsig->ps_refcnt == 0) { - if (p->p_sigacts != &p->p_uarea->u_sigacts) - FREE(p->p_sigacts, M_SUBPROC); - FREE(p->p_procsig, M_SUBPROC); - p->p_procsig = NULL; - } + sigacts_free(p->p_sigacts); + p->p_sigacts = NULL; /* * do any thread-system specific cleanups diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c index 17387f8bb5c7..0ba17cec3f7a 100644 --- a/sys/kern/kern_fork.c +++ b/sys/kern/kern_fork.c @@ -214,7 +214,6 @@ fork1(td, flags, pages, procp) struct kse *ke2; struct ksegrp *kg2; struct sigacts *newsigacts; - struct procsig *newprocsig; int error; /* Can't copy and clear */ @@ -412,15 +411,10 @@ again: /* * Malloc things while we don't hold any locks. */ - if (flags & RFSIGSHARE) { - MALLOC(newsigacts, struct sigacts *, - sizeof(struct sigacts), M_SUBPROC, M_WAITOK); - newprocsig = NULL; - } else { + if (flags & RFSIGSHARE) newsigacts = NULL; - MALLOC(newprocsig, struct procsig *, sizeof(struct procsig), - M_SUBPROC, M_WAITOK); - } + else + newsigacts = sigacts_alloc(); /* * Copy filedesc. @@ -477,7 +471,7 @@ again: /* * Duplicate sub-structures as needed. * Increase reference counts on shared objects. - * The p_stats and p_sigacts substructs are set in vm_forkproc. + * The p_stats substruct is set in vm_forkproc. */ p2->p_flag = 0; if (p1->p_flag & P_PROFIL) @@ -497,25 +491,10 @@ again: pargs_hold(p2->p_args); if (flags & RFSIGSHARE) { - p2->p_procsig = p1->p_procsig; - p2->p_procsig->ps_refcnt++; - if (p1->p_sigacts == &p1->p_uarea->u_sigacts) { - /* - * Set p_sigacts to the new shared structure. - * Note that this is updating p1->p_sigacts at the - * same time, since p_sigacts is just a pointer to - * the shared p_procsig->ps_sigacts. - */ - p2->p_sigacts = newsigacts; - newsigacts = NULL; - *p2->p_sigacts = p1->p_uarea->u_sigacts; - } + p2->p_sigacts = sigacts_hold(p1->p_sigacts); } else { - p2->p_procsig = newprocsig; - newprocsig = NULL; - bcopy(p1->p_procsig, p2->p_procsig, sizeof(*p2->p_procsig)); - p2->p_procsig->ps_refcnt = 1; - p2->p_sigacts = NULL; /* finished in vm_forkproc() */ + sigacts_copy(newsigacts, p1->p_sigacts); + p2->p_sigacts = newsigacts; } if (flags & RFLINUXTHPN) p2->p_sigparent = SIGUSR1; @@ -647,9 +626,6 @@ again: p2->p_acflag = AFORK; PROC_UNLOCK(p2); - KASSERT(newprocsig == NULL, ("unused newprocsig")); - if (newsigacts != NULL) - FREE(newsigacts, M_SUBPROC); /* * Finish creating the child process. It will return via a different * execution path later. (ie: directly into user mode) diff --git a/sys/kern/kern_kthread.c b/sys/kern/kern_kthread.c index d4846dda9635..7d38520e4382 100644 --- a/sys/kern/kern_kthread.c +++ b/sys/kern/kern_kthread.c @@ -94,7 +94,9 @@ kthread_create(void (*func)(void *), void *arg, /* this is a non-swapped system process */ PROC_LOCK(p2); p2->p_flag |= P_SYSTEM | P_KTHREAD; - p2->p_procsig->ps_flag |= PS_NOCLDWAIT; + mtx_lock(&p2->p_sigacts->ps_mtx); + p2->p_sigacts->ps_flag |= PS_NOCLDWAIT; + mtx_unlock(&p2->p_sigacts->ps_mtx); _PHOLD(p2); PROC_UNLOCK(p2); diff --git a/sys/kern/kern_proc.c b/sys/kern/kern_proc.c index 6810537fb121..766567453493 100644 --- a/sys/kern/kern_proc.c +++ b/sys/kern/kern_proc.c @@ -623,6 +623,7 @@ fill_kinfo_proc(p, kp) struct tty *tp; struct session *sp; struct timeval tv; + struct sigacts *ps; td = FIRST_THREAD_IN_PROC(p); @@ -653,9 +654,12 @@ fill_kinfo_proc(p, kp) kp->ki_rgid = p->p_ucred->cr_rgid; kp->ki_svgid = p->p_ucred->cr_svgid; } - if (p->p_procsig) { - kp->ki_sigignore = p->p_procsig->ps_sigignore; - kp->ki_sigcatch = p->p_procsig->ps_sigcatch; + if (p->p_sigacts) { + ps = p->p_sigacts; + mtx_lock(&ps->ps_mtx); + kp->ki_sigignore = ps->ps_sigignore; + kp->ki_sigcatch = ps->ps_sigcatch; + mtx_unlock(&ps->ps_mtx); } mtx_lock_spin(&sched_lock); if (p->p_state != PRS_NEW && diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c index dd2fb3ee68ba..abe10df5c302 100644 --- a/sys/kern/kern_sig.c +++ b/sys/kern/kern_sig.c @@ -181,6 +181,7 @@ int cursig(struct thread *td) { PROC_LOCK_ASSERT(td->td_proc, MA_OWNED); + mtx_assert(&td->td_proc->p_sigacts->ps_mtx, MA_OWNED); mtx_assert(&sched_lock, MA_NOTOWNED); return (SIGPENDING(td) ? issignal(td) : 0); } @@ -267,16 +268,16 @@ kern_sigaction(td, sig, act, oact, flags) struct sigaction *act, *oact; int flags; { - register struct sigacts *ps; + struct sigacts *ps; struct thread *td0; struct proc *p = td->td_proc; if (!_SIG_VALID(sig)) return (EINVAL); - mtx_lock(&Giant); PROC_LOCK(p); ps = p->p_sigacts; + mtx_lock(&ps->ps_mtx); if (oact) { oact->sa_handler = ps->ps_sigact[_SIG_IDX(sig)]; oact->sa_mask = ps->ps_catchmask[_SIG_IDX(sig)]; @@ -291,16 +292,16 @@ kern_sigaction(td, sig, act, oact, flags) oact->sa_flags |= SA_NODEFER; if (SIGISMEMBER(ps->ps_siginfo, sig)) oact->sa_flags |= SA_SIGINFO; - if (sig == SIGCHLD && p->p_procsig->ps_flag & PS_NOCLDSTOP) + if (sig == SIGCHLD && ps->ps_flag & PS_NOCLDSTOP) oact->sa_flags |= SA_NOCLDSTOP; - if (sig == SIGCHLD && p->p_procsig->ps_flag & PS_NOCLDWAIT) + if (sig == SIGCHLD && ps->ps_flag & PS_NOCLDWAIT) oact->sa_flags |= SA_NOCLDWAIT; } if (act) { if ((sig == SIGKILL || sig == SIGSTOP) && act->sa_handler != SIG_DFL) { + mtx_unlock(&ps->ps_mtx); PROC_UNLOCK(p); - mtx_unlock(&Giant); return (EINVAL); } @@ -342,9 +343,9 @@ kern_sigaction(td, sig, act, oact, flags) #endif if (sig == SIGCHLD) { if (act->sa_flags & SA_NOCLDSTOP) - p->p_procsig->ps_flag |= PS_NOCLDSTOP; + ps->ps_flag |= PS_NOCLDSTOP; else - p->p_procsig->ps_flag &= ~PS_NOCLDSTOP; + ps->ps_flag &= ~PS_NOCLDSTOP; if (act->sa_flags & SA_NOCLDWAIT) { /* * Paranoia: since SA_NOCLDWAIT is implemented @@ -353,20 +354,20 @@ kern_sigaction(td, sig, act, oact, flags) * is forbidden to set SA_NOCLDWAIT. */ if (p->p_pid == 1) - p->p_procsig->ps_flag &= ~PS_NOCLDWAIT; + ps->ps_flag &= ~PS_NOCLDWAIT; else - p->p_procsig->ps_flag |= PS_NOCLDWAIT; + ps->ps_flag |= PS_NOCLDWAIT; } else - p->p_procsig->ps_flag &= ~PS_NOCLDWAIT; + ps->ps_flag &= ~PS_NOCLDWAIT; if (ps->ps_sigact[_SIG_IDX(SIGCHLD)] == SIG_IGN) - p->p_procsig->ps_flag |= PS_CLDSIGIGN; + ps->ps_flag |= PS_CLDSIGIGN; else - p->p_procsig->ps_flag &= ~PS_CLDSIGIGN; + ps->ps_flag &= ~PS_CLDSIGIGN; } /* - * Set bit in p_sigignore for signals that are set to SIG_IGN, + * Set bit in ps_sigignore for signals that are set to SIG_IGN, * and for signals set to SIG_DFL where the default is to - * ignore. However, don't put SIGCONT in p_sigignore, as we + * ignore. However, don't put SIGCONT in ps_sigignore, as we * have to restart the process. */ if (ps->ps_sigact[_SIG_IDX(sig)] == SIG_IGN || @@ -378,14 +379,14 @@ kern_sigaction(td, sig, act, oact, flags) SIGDELSET(td0->td_siglist, sig); if (sig != SIGCONT) /* easier in psignal */ - SIGADDSET(p->p_sigignore, sig); - SIGDELSET(p->p_sigcatch, sig); + SIGADDSET(ps->ps_sigignore, sig); + SIGDELSET(ps->ps_sigcatch, sig); } else { - SIGDELSET(p->p_sigignore, sig); + SIGDELSET(ps->ps_sigignore, sig); if (ps->ps_sigact[_SIG_IDX(sig)] == SIG_DFL) - SIGDELSET(p->p_sigcatch, sig); + SIGDELSET(ps->ps_sigcatch, sig); else - SIGADDSET(p->p_sigcatch, sig); + SIGADDSET(ps->ps_sigcatch, sig); } #ifdef COMPAT_FREEBSD4 if (ps->ps_sigact[_SIG_IDX(sig)] == SIG_IGN || @@ -404,8 +405,8 @@ kern_sigaction(td, sig, act, oact, flags) SIGADDSET(ps->ps_osigset, sig); #endif } + mtx_unlock(&ps->ps_mtx); PROC_UNLOCK(p); - mtx_unlock(&Giant); return (0); } @@ -543,11 +544,15 @@ siginit(p) struct proc *p; { register int i; + struct sigacts *ps; PROC_LOCK(p); + ps = p->p_sigacts; + mtx_lock(&ps->ps_mtx); for (i = 1; i <= NSIG; i++) if (sigprop(i) & SA_IGNORE && i != SIGCONT) - SIGADDSET(p->p_sigignore, i); + SIGADDSET(ps->ps_sigignore, i); + mtx_unlock(&ps->ps_mtx); PROC_UNLOCK(p); } @@ -568,12 +573,13 @@ execsigs(p) */ PROC_LOCK_ASSERT(p, MA_OWNED); ps = p->p_sigacts; - while (SIGNOTEMPTY(p->p_sigcatch)) { - sig = sig_ffs(&p->p_sigcatch); - SIGDELSET(p->p_sigcatch, sig); + mtx_lock(&ps->ps_mtx); + while (SIGNOTEMPTY(ps->ps_sigcatch)) { + sig = sig_ffs(&ps->ps_sigcatch); + SIGDELSET(ps->ps_sigcatch, sig); if (sigprop(sig) & SA_IGNORE) { if (sig != SIGCONT) - SIGADDSET(p->p_sigignore, sig); + SIGADDSET(ps->ps_sigignore, sig); SIGDELSET(p->p_siglist, sig); /* * There is only one thread at this point. @@ -597,9 +603,10 @@ execsigs(p) /* * Reset no zombies if child dies flag as Solaris does. */ - p->p_procsig->ps_flag &= ~(PS_NOCLDWAIT | PS_CLDSIGIGN); + ps->ps_flag &= ~(PS_NOCLDWAIT | PS_CLDSIGIGN); if (ps->ps_sigact[_SIG_IDX(SIGCHLD)] == SIG_IGN) ps->ps_sigact[_SIG_IDX(SIGCHLD)] = SIG_DFL; + mtx_unlock(&ps->ps_mtx); } /* @@ -822,14 +829,13 @@ kern_sigtimedwait(struct thread *td, sigset_t set, siginfo_t *info, sig = 0; SIG_CANTMASK(set); - mtx_lock(&Giant); PROC_LOCK(p); - ps = p->p_sigacts; oldmask = td->td_sigmask; td->td_sigmask = set; signotify(td); + mtx_lock(&ps->ps_mtx); sig = cursig(td); if (sig) goto out; @@ -850,7 +856,9 @@ kern_sigtimedwait(struct thread *td, sigset_t set, siginfo_t *info, } else hz = 0; + mtx_unlock(&ps->ps_mtx); error = msleep(ps, &p->p_mtx, PPAUSE|PCATCH, "pause", hz); + mtx_lock(&ps->ps_mtx); if (error == EINTR) error = 0; else if (error) @@ -863,6 +871,7 @@ out: sig_t action; action = ps->ps_sigact[_SIG_IDX(sig)]; + mtx_unlock(&ps->ps_mtx); #ifdef KTRACE if (KTRPOINT(td, KTR_PSIG)) ktrpsig(sig, action, td->td_flags & TDF_OLDMASK ? @@ -877,11 +886,9 @@ out: SIGDELSET(td->td_siglist, sig); info->si_signo = sig; info->si_code = 0; - } - + } else + mtx_unlock(&ps->ps_mtx); PROC_UNLOCK(p); - mtx_unlock(&Giant); - return (error); } @@ -1330,39 +1337,30 @@ kill(td, uap) register struct kill_args *uap; { register struct proc *p; - int error = 0; + int error; if ((u_int)uap->signum > _SIG_MAXSIG) return (EINVAL); - mtx_lock(&Giant); if (uap->pid > 0) { /* kill single process */ - if ((p = pfind(uap->pid)) == NULL) { - error = ESRCH; - } else if ((error = p_cansignal(td, p, uap->signum)) != 0) { - PROC_UNLOCK(p); - } else { - if (uap->signum) - psignal(p, uap->signum); - PROC_UNLOCK(p); - error = 0; - } - } else { - switch (uap->pid) { - case -1: /* broadcast signal */ - error = killpg1(td, uap->signum, 0, 1); - break; - case 0: /* signal own process group */ - error = killpg1(td, uap->signum, 0, 0); - break; - default: /* negative explicit process group */ - error = killpg1(td, uap->signum, -uap->pid, 0); - break; - } + if ((p = pfind(uap->pid)) == NULL) + return (ESRCH); + error = p_cansignal(td, p, uap->signum); + if (error == 0 && uap->signum) + psignal(p, uap->signum); + PROC_UNLOCK(p); + return (error); } - mtx_unlock(&Giant); - return(error); + switch (uap->pid) { + case -1: /* broadcast signal */ + return (killpg1(td, uap->signum, 0, 1)); + case 0: /* signal own process group */ + return (killpg1(td, uap->signum, 0, 0)); + default: /* negative explicit process group */ + return (killpg1(td, uap->signum, -uap->pid, 0)); + } + /* NOTREACHED */ } #if defined(COMPAT_43) || defined(COMPAT_SUNOS) @@ -1381,14 +1379,10 @@ okillpg(td, uap) struct thread *td; register struct okillpg_args *uap; { - int error; if ((u_int)uap->signum > _SIG_MAXSIG) return (EINVAL); - mtx_lock(&Giant); - error = killpg1(td, uap->signum, uap->pgid, 0); - mtx_unlock(&Giant); - return (error); + return (killpg1(td, uap->signum, uap->pgid, 0)); } #endif /* COMPAT_43 || COMPAT_SUNOS */ @@ -1451,7 +1445,8 @@ trapsignal(struct thread *td, int sig, u_long code) PROC_LOCK(p); ps = p->p_sigacts; - if ((p->p_flag & P_TRACED) == 0 && SIGISMEMBER(p->p_sigcatch, sig) && + mtx_lock(&ps->ps_mtx); + if ((p->p_flag & P_TRACED) == 0 && SIGISMEMBER(ps->ps_sigcatch, sig) && !SIGISMEMBER(td->td_sigmask, sig)) { p->p_stats->p_ru.ru_nsignals++; #ifdef KTRACE @@ -1468,13 +1463,15 @@ trapsignal(struct thread *td, int sig, u_long code) /* * See kern_sigaction() for origin of this code. */ - SIGDELSET(p->p_sigcatch, sig); + SIGDELSET(ps->ps_sigcatch, sig); if (sig != SIGCONT && sigprop(sig) & SA_IGNORE) - SIGADDSET(p->p_sigignore, sig); + SIGADDSET(ps->ps_sigignore, sig); ps->ps_sigact[_SIG_IDX(sig)] = SIG_DFL; } + mtx_unlock(&ps->ps_mtx); } else { + 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); @@ -1528,6 +1525,8 @@ sigtd(struct proc *p, int sig, int prop) * regardless of the signal action (eg, blocked or ignored). * * Other ignored signals are discarded immediately. + * + * MPSAFE */ void psignal(struct proc *p, int sig) @@ -1546,6 +1545,9 @@ psignal(struct proc *p, int sig) tdsignal(td, sig); } +/* + * MPSAFE + */ void tdsignal(struct thread *td, int sig) { @@ -1554,12 +1556,13 @@ tdsignal(struct thread *td, int sig) sigset_t *siglist; struct thread *td0; register int prop; - + struct sigacts *ps; KASSERT(_SIG_VALID(sig), ("tdsignal(): invalid signal %d\n", sig)); p = td->td_proc; + ps = p->p_sigacts; PROC_LOCK_ASSERT(p, MA_OWNED); KNOTE(&p->p_klist, NOTE_SIGNAL | sig); @@ -1586,18 +1589,23 @@ tdsignal(struct thread *td, int sig) /* * If the signal is being ignored, * then we forget about it immediately. - * (Note: we don't set SIGCONT in p_sigignore, + * (Note: we don't set SIGCONT in ps_sigignore, * and if it is set to SIG_IGN, * action will be SIG_DFL here.) */ - if (SIGISMEMBER(p->p_sigignore, sig) || (p->p_flag & P_WEXIT)) + mtx_lock(&ps->ps_mtx); + if (SIGISMEMBER(ps->ps_sigignore, sig) || + (p->p_flag & P_WEXIT)) { + mtx_unlock(&ps->ps_mtx); return; + } if (SIGISMEMBER(td->td_sigmask, sig)) action = SIG_HOLD; - else if (SIGISMEMBER(p->p_sigcatch, sig)) + else if (SIGISMEMBER(ps->ps_sigcatch, sig)) action = SIG_CATCH; else action = SIG_DFL; + mtx_unlock(&ps->ps_mtx); } if (prop & SA_CONT) { @@ -1890,13 +1898,14 @@ issignal(td) struct thread *td; { struct proc *p; + struct sigacts *ps; sigset_t sigpending; register int sig, prop; p = td->td_proc; + ps = p->p_sigacts; + mtx_assert(&ps->ps_mtx, MA_OWNED); PROC_LOCK_ASSERT(p, MA_OWNED); - WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, &p->p_mtx.mtx_object, - "Checking for signals"); for (;;) { int traced = (p->p_flag & P_TRACED) || (p->p_stops & S_SIG); @@ -1916,7 +1925,7 @@ issignal(td) * We should see pending but ignored signals * only if P_TRACED was on when they were posted. */ - if (SIGISMEMBER(p->p_sigignore, sig) && (traced == 0)) { + if (SIGISMEMBER(ps->ps_sigignore, sig) && (traced == 0)) { SIGDELSET(td->td_siglist, sig); continue; } @@ -1924,6 +1933,9 @@ issignal(td) /* * If traced, always stop. */ + mtx_unlock(&ps->ps_mtx); + WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, + &p->p_mtx.mtx_object, "Stopping for traced signal"); p->p_xstat = sig; PROC_LOCK(p->p_pptr); psignal(p->p_pptr, SIGCHLD); @@ -1938,11 +1950,12 @@ issignal(td) mtx_unlock_spin(&sched_lock); PICKUP_GIANT(); PROC_LOCK(p); + mtx_lock(&ps->ps_mtx); /* * If the traced bit got turned off, go back up * to the top to rescan signals. This ensures - * that p_sig* and ps_sigact are consistent. + * that p_sig* and p_sigacts are consistent. */ if ((p->p_flag & P_TRACED) == 0) continue; @@ -2001,6 +2014,9 @@ issignal(td) (p->p_pgrp->pg_jobc == 0 && prop & SA_TTYSTOP)) break; /* == ignore */ + mtx_unlock(&ps->ps_mtx); + WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, + &p->p_mtx.mtx_object, "Catching SIGSTOP"); p->p_flag |= P_STOPPED_SIG; p->p_xstat = sig; mtx_lock_spin(&sched_lock); @@ -2013,6 +2029,7 @@ issignal(td) mtx_unlock_spin(&sched_lock); PICKUP_GIANT(); PROC_LOCK(p); + mtx_lock(&ps->ps_mtx); break; } else if (prop & SA_IGNORE) { /* @@ -2063,10 +2080,14 @@ stop(struct proc *p) wakeup(p->p_pptr); } +/* + * MPSAFE + */ void thread_stopped(struct proc *p) { struct proc *p1 = curthread->td_proc; + struct sigacts *ps; int n; PROC_LOCK_ASSERT(p, MA_OWNED); @@ -2078,10 +2099,13 @@ thread_stopped(struct proc *p) mtx_unlock_spin(&sched_lock); stop(p); PROC_LOCK(p->p_pptr); - if ((p->p_pptr->p_procsig->ps_flag & - PS_NOCLDSTOP) == 0) { + ps = p->p_pptr->p_sigacts; + mtx_lock(&ps->ps_mtx); + if ((ps->ps_flag & PS_NOCLDSTOP) == 0) { + mtx_unlock(&ps->ps_mtx); psignal(p->p_pptr, SIGCHLD); - } + } else + mtx_unlock(&ps->ps_mtx); PROC_UNLOCK(p->p_pptr); mtx_lock_spin(&sched_lock); } @@ -2106,6 +2130,7 @@ postsig(sig) PROC_LOCK_ASSERT(p, MA_OWNED); ps = p->p_sigacts; + mtx_assert(&ps->ps_mtx, MA_OWNED); SIGDELSET(td->td_siglist, sig); action = ps->ps_sigact[_SIG_IDX(sig)]; #ifdef KTRACE @@ -2120,6 +2145,7 @@ postsig(sig) * Default action, where the default is to kill * the process. (Other cases were ignored above.) */ + mtx_unlock(&ps->ps_mtx); sigexit(td, sig); /* NOTREACHED */ } else { @@ -2153,10 +2179,10 @@ postsig(sig) /* * See kern_sigaction() for origin of this code. */ - SIGDELSET(p->p_sigcatch, sig); + SIGDELSET(ps->ps_sigcatch, sig); if (sig != SIGCONT && sigprop(sig) & SA_IGNORE) - SIGADDSET(p->p_sigignore, sig); + SIGADDSET(ps->ps_sigignore, sig); ps->ps_sigact[_SIG_IDX(sig)] = SIG_DFL; } p->p_stats->p_ru.ru_nsignals++; @@ -2199,6 +2225,8 @@ killproc(p, why) * signal state. Mark the accounting record with the signal termination. * If dumping core, save the signal number for the debugger. Calls exit and * does not return. + * + * MPSAFE */ void sigexit(td, sig) @@ -2443,11 +2471,9 @@ nosys(td, args) { struct proc *p = td->td_proc; - mtx_lock(&Giant); PROC_LOCK(p); psignal(p, SIGSYS); PROC_UNLOCK(p); - mtx_unlock(&Giant); return (ENOSYS); } @@ -2532,3 +2558,57 @@ filt_signal(struct knote *kn, long hint) } return (kn->kn_data != 0); } + +struct sigacts * +sigacts_alloc(void) +{ + struct sigacts *ps; + + ps = malloc(sizeof(struct sigacts), M_SUBPROC, M_WAITOK | M_ZERO); + ps->ps_refcnt = 1; + mtx_init(&ps->ps_mtx, "sigacts", NULL, MTX_DEF); + return (ps); +} + +void +sigacts_free(struct sigacts *ps) +{ + + mtx_lock(&ps->ps_mtx); + ps->ps_refcnt--; + if (ps->ps_refcnt == 0) { + mtx_destroy(&ps->ps_mtx); + free(ps, M_SUBPROC); + } else + mtx_unlock(&ps->ps_mtx); +} + +struct sigacts * +sigacts_hold(struct sigacts *ps) +{ + mtx_lock(&ps->ps_mtx); + ps->ps_refcnt++; + mtx_unlock(&ps->ps_mtx); + return (ps); +} + +void +sigacts_copy(struct sigacts *dest, struct sigacts *src) +{ + + KASSERT(dest->ps_refcnt == 1, ("sigacts_copy to shared dest")); + mtx_lock(&src->ps_mtx); + bcopy(src, dest, offsetof(struct sigacts, ps_refcnt)); + mtx_unlock(&src->ps_mtx); +} + +int +sigacts_shared(struct sigacts *ps) +{ + int shared; + + mtx_lock(&ps->ps_mtx); + shared = ps->ps_refcnt > 1; + mtx_unlock(&ps->ps_mtx); + return (shared); +} diff --git a/sys/kern/kern_synch.c b/sys/kern/kern_synch.c index d648e9e311e9..fbf6ed3275af 100644 --- a/sys/kern/kern_synch.c +++ b/sys/kern/kern_synch.c @@ -230,7 +230,9 @@ msleep(ident, mtx, priority, wmesg, timo) td->td_flags |= TDF_SINTR; mtx_unlock_spin(&sched_lock); PROC_LOCK(p); + mtx_lock(&p->p_sigacts->ps_mtx); sig = cursig(td); + mtx_unlock(&p->p_sigacts->ps_mtx); if (sig == 0 && thread_suspend_check(1)) sig = SIGSTOP; mtx_lock_spin(&sched_lock); @@ -291,12 +293,14 @@ msleep(ident, mtx, priority, wmesg, timo) if (rval == 0 && catch) { PROC_LOCK(p); /* XXX: shouldn't we always be calling cursig() */ + mtx_lock(&p->p_sigacts->ps_mtx); if (sig != 0 || (sig = cursig(td))) { if (SIGISMEMBER(p->p_sigacts->ps_sigintr, sig)) rval = EINTR; else rval = ERESTART; } + mtx_unlock(&p->p_sigacts->ps_mtx); PROC_UNLOCK(p); } #ifdef KTRACE diff --git a/sys/kern/subr_trap.c b/sys/kern/subr_trap.c index b2fc0fc5abaa..9eaa5b80307b 100644 --- a/sys/kern/subr_trap.c +++ b/sys/kern/subr_trap.c @@ -245,10 +245,12 @@ ast(struct trapframe *framep) sigs = 0; PROC_LOCK(p); + mtx_lock(&p->p_sigacts->ps_mtx); while ((sig = cursig(td)) != 0) { postsig(sig); sigs++; } + mtx_unlock(&p->p_sigacts->ps_mtx); PROC_UNLOCK(p); if (p->p_flag & P_THREADED && sigs) { struct kse_upcall *ku = td->td_upcall; diff --git a/sys/kern/tty.c b/sys/kern/tty.c index 33ecd6e7de10..0b543f176a59 100644 --- a/sys/kern/tty.c +++ b/sys/kern/tty.c @@ -776,7 +776,7 @@ ttioctl(struct tty *tp, u_long cmd, void *data, int flag) sx_slock(&proctree_lock); PROC_LOCK(p); while (isbackground(p, tp) && !(p->p_flag & P_PPWAIT) && - !SIGISMEMBER(p->p_sigignore, SIGTTOU) && + !SIGISMEMBER(p->p_sigacts->ps_sigignore, SIGTTOU) && !SIGISMEMBER(td->td_sigmask, SIGTTOU)) { pgrp = p->p_pgrp; PROC_UNLOCK(p); @@ -1934,7 +1934,7 @@ loop: PROC_LOCK(p); if (isbackground(p, tp) && ISSET(tp->t_lflag, TOSTOP) && !(p->p_flag & P_PPWAIT) && - !SIGISMEMBER(p->p_sigignore, SIGTTOU) && + !SIGISMEMBER(p->p_sigacts->ps_sigignore, SIGTTOU) && !SIGISMEMBER(td->td_sigmask, SIGTTOU)) { if (p->p_pgrp->pg_jobc == 0) { PROC_UNLOCK(p); diff --git a/sys/kern/tty_pty.c b/sys/kern/tty_pty.c index b104e6b76d89..eadcf086f021 100644 --- a/sys/kern/tty_pty.c +++ b/sys/kern/tty_pty.c @@ -235,7 +235,7 @@ again: while (isbackground(p, tp)) { sx_slock(&proctree_lock); PROC_LOCK(p); - if (SIGISMEMBER(p->p_sigignore, SIGTTIN) || + if (SIGISMEMBER(p->p_sigacts->ps_sigignore, SIGTTIN) || SIGISMEMBER(td->td_sigmask, SIGTTIN) || p->p_pgrp->pg_jobc == 0 || p->p_flag & P_PPWAIT) { PROC_UNLOCK(p); diff --git a/sys/netncp/ncp_ncp.c b/sys/netncp/ncp_ncp.c index 0541793c0ff5..1d29afe2b329 100644 --- a/sys/netncp/ncp_ncp.c +++ b/sys/netncp/ncp_ncp.c @@ -88,7 +88,9 @@ ncp_chkintr(struct ncp_conn *conn, struct thread *td) tmpset = p->p_siglist; SIGSETOR(tmpset, td->td_siglist); SIGSETNAND(tmpset, td->td_sigmask); - SIGSETNAND(tmpset, p->p_sigignore); + mtx_lock(&p->p_sigacts->ps_mtx); + SIGSETNAND(tmpset, p->p_sigacts->ps_sigignore); + mtx_unlock(&p->p_sigacts->ps_mtx); if (SIGNOTEMPTY(td->td_siglist) && NCP_SIGMASK(tmpset)) { PROC_UNLOCK(p); return EINTR; diff --git a/sys/netsmb/smb_subr.c b/sys/netsmb/smb_subr.c index 0e0356054d23..1650ece671df 100644 --- a/sys/netsmb/smb_subr.c +++ b/sys/netsmb/smb_subr.c @@ -82,7 +82,9 @@ smb_td_intr(struct thread *td) tmpset = p->p_siglist; SIGSETOR(tmpset, td->td_siglist); SIGSETNAND(tmpset, td->td_sigmask); - SIGSETNAND(tmpset, p->p_sigignore); + mtx_lock(&p->p_sigacts->ps_mtx); + SIGSETNAND(tmpset, p->p_sigacts->ps_sigignore); + mtx_unlock(&p->p_sigacts->ps_mtx); if (SIGNOTEMPTY(td->td_siglist) && SMB_SIGMASK(tmpset)) { PROC_UNLOCK(p); return EINTR; diff --git a/sys/nfsclient/nfs_socket.c b/sys/nfsclient/nfs_socket.c index 3949b747b56b..aaa2f7ad3120 100644 --- a/sys/nfsclient/nfs_socket.c +++ b/sys/nfsclient/nfs_socket.c @@ -1239,7 +1239,9 @@ nfs_sigintr(struct nfsmount *nmp, struct nfsreq *rep, struct thread *td) PROC_LOCK(p); tmpset = p->p_siglist; SIGSETNAND(tmpset, td->td_sigmask); - SIGSETNAND(tmpset, p->p_sigignore); + mtx_lock(&p->p_sigacts->ps_mtx); + SIGSETNAND(tmpset, p->p_sigacts->ps_sigignore); + mtx_unlock(&p->p_sigacts->ps_mtx); if (SIGNOTEMPTY(p->p_siglist) && NFSINT_SIGMASK(tmpset)) { PROC_UNLOCK(p); return (EINTR); diff --git a/sys/pc98/i386/machdep.c b/sys/pc98/i386/machdep.c index b9013a22da35..4797ae16317b 100644 --- a/sys/pc98/i386/machdep.c +++ b/sys/pc98/i386/machdep.c @@ -315,6 +315,7 @@ osendsig(catcher, sig, mask, code) p = td->td_proc; PROC_LOCK_ASSERT(p, MA_OWNED); psp = p->p_sigacts; + mtx_assert(&psp->ps_mtx, MA_OWNED); regs = td->td_frame; oonstack = sigonstack(regs->tf_esp); @@ -328,7 +329,6 @@ osendsig(catcher, sig, mask, code) #endif } else fp = (struct osigframe *)regs->tf_esp - 1; - PROC_UNLOCK(p); /* Translate the signal if appropriate. */ if (p->p_sysent->sv_sigtbl && sig <= p->p_sysent->sv_sigsize) @@ -337,8 +337,7 @@ osendsig(catcher, sig, mask, code) /* Build the argument list for the signal handler. */ sf.sf_signum = sig; sf.sf_scp = (register_t)&fp->sf_siginfo.si_sc; - PROC_LOCK(p); - if (SIGISMEMBER(p->p_sigacts->ps_siginfo, sig)) { + if (SIGISMEMBER(psp->ps_siginfo, sig)) { /* Signal handler installed with SA_SIGINFO. */ sf.sf_arg2 = (register_t)&fp->sf_siginfo; sf.sf_siginfo.si_signo = sig; @@ -350,6 +349,7 @@ osendsig(catcher, sig, mask, code) sf.sf_addr = regs->tf_err; sf.sf_ahu.sf_handler = catcher; } + mtx_unlock(&psp->ps_mtx); PROC_UNLOCK(p); /* Save most if not all of trap frame. */ @@ -422,6 +422,7 @@ osendsig(catcher, sig, mask, code) load_gs(_udatasel); regs->tf_ss = _udatasel; PROC_LOCK(p); + mtx_lock(&psp->ps_mtx); } #endif /* COMPAT_43 */ @@ -444,6 +445,7 @@ freebsd4_sendsig(catcher, sig, mask, code) p = td->td_proc; PROC_LOCK_ASSERT(p, MA_OWNED); psp = p->p_sigacts; + mtx_assert(&psp->ps_mtx, MA_OWNED); regs = td->td_frame; oonstack = sigonstack(regs->tf_esp); @@ -467,7 +469,6 @@ freebsd4_sendsig(catcher, sig, mask, code) #endif } else sfp = (struct sigframe4 *)regs->tf_esp - 1; - PROC_UNLOCK(p); /* Translate the signal if appropriate. */ if (p->p_sysent->sv_sigtbl && sig <= p->p_sysent->sv_sigsize) @@ -476,8 +477,7 @@ freebsd4_sendsig(catcher, sig, mask, code) /* Build the argument list for the signal handler. */ sf.sf_signum = sig; sf.sf_ucontext = (register_t)&sfp->sf_uc; - PROC_LOCK(p); - if (SIGISMEMBER(p->p_sigacts->ps_siginfo, sig)) { + if (SIGISMEMBER(psp->ps_siginfo, sig)) { /* Signal handler installed with SA_SIGINFO. */ sf.sf_siginfo = (register_t)&sfp->sf_si; sf.sf_ahu.sf_action = (__siginfohandler_t *)catcher; @@ -492,6 +492,7 @@ freebsd4_sendsig(catcher, sig, mask, code) sf.sf_addr = regs->tf_err; sf.sf_ahu.sf_handler = catcher; } + mtx_unlock(&psp->ps_mtx); PROC_UNLOCK(p); /* @@ -543,6 +544,7 @@ freebsd4_sendsig(catcher, sig, mask, code) regs->tf_fs = _udatasel; regs->tf_ss = _udatasel; PROC_LOCK(p); + mtx_lock(&psp->ps_mtx); } #endif /* COMPAT_FREEBSD4 */ @@ -565,6 +567,7 @@ sendsig(catcher, sig, mask, code) p = td->td_proc; PROC_LOCK_ASSERT(p, MA_OWNED); psp = p->p_sigacts; + mtx_assert(&psp->ps_mtx,.MA_OWNED); #ifdef COMPAT_FREEBSD4 if (SIGISMEMBER(psp->ps_freebsd4, sig)) { freebsd4_sendsig(catcher, sig, mask, code); @@ -605,7 +608,6 @@ sendsig(catcher, sig, mask, code) sp = (char *)regs->tf_esp - sizeof(struct sigframe); /* Align to 16 bytes. */ sfp = (struct sigframe *)((unsigned int)sp & ~0xF); - PROC_UNLOCK(p); /* Translate the signal if appropriate. */ if (p->p_sysent->sv_sigtbl && sig <= p->p_sysent->sv_sigsize) @@ -614,8 +616,7 @@ sendsig(catcher, sig, mask, code) /* Build the argument list for the signal handler. */ sf.sf_signum = sig; sf.sf_ucontext = (register_t)&sfp->sf_uc; - PROC_LOCK(p); - if (SIGISMEMBER(p->p_sigacts->ps_siginfo, sig)) { + if (SIGISMEMBER(psp->ps_siginfo, sig)) { /* Signal handler installed with SA_SIGINFO. */ sf.sf_siginfo = (register_t)&sfp->sf_si; sf.sf_ahu.sf_action = (__siginfohandler_t *)catcher; @@ -630,6 +631,7 @@ sendsig(catcher, sig, mask, code) sf.sf_addr = regs->tf_err; sf.sf_ahu.sf_handler = catcher; } + mtx_unlock(&psp->ps_mtx); PROC_UNLOCK(p); /* @@ -681,6 +683,7 @@ sendsig(catcher, sig, mask, code) regs->tf_fs = _udatasel; regs->tf_ss = _udatasel; PROC_LOCK(p); + mtx_lock(&psp->ps_mtx); } /* diff --git a/sys/pc98/pc98/machdep.c b/sys/pc98/pc98/machdep.c index b9013a22da35..4797ae16317b 100644 --- a/sys/pc98/pc98/machdep.c +++ b/sys/pc98/pc98/machdep.c @@ -315,6 +315,7 @@ osendsig(catcher, sig, mask, code) p = td->td_proc; PROC_LOCK_ASSERT(p, MA_OWNED); psp = p->p_sigacts; + mtx_assert(&psp->ps_mtx, MA_OWNED); regs = td->td_frame; oonstack = sigonstack(regs->tf_esp); @@ -328,7 +329,6 @@ osendsig(catcher, sig, mask, code) #endif } else fp = (struct osigframe *)regs->tf_esp - 1; - PROC_UNLOCK(p); /* Translate the signal if appropriate. */ if (p->p_sysent->sv_sigtbl && sig <= p->p_sysent->sv_sigsize) @@ -337,8 +337,7 @@ osendsig(catcher, sig, mask, code) /* Build the argument list for the signal handler. */ sf.sf_signum = sig; sf.sf_scp = (register_t)&fp->sf_siginfo.si_sc; - PROC_LOCK(p); - if (SIGISMEMBER(p->p_sigacts->ps_siginfo, sig)) { + if (SIGISMEMBER(psp->ps_siginfo, sig)) { /* Signal handler installed with SA_SIGINFO. */ sf.sf_arg2 = (register_t)&fp->sf_siginfo; sf.sf_siginfo.si_signo = sig; @@ -350,6 +349,7 @@ osendsig(catcher, sig, mask, code) sf.sf_addr = regs->tf_err; sf.sf_ahu.sf_handler = catcher; } + mtx_unlock(&psp->ps_mtx); PROC_UNLOCK(p); /* Save most if not all of trap frame. */ @@ -422,6 +422,7 @@ osendsig(catcher, sig, mask, code) load_gs(_udatasel); regs->tf_ss = _udatasel; PROC_LOCK(p); + mtx_lock(&psp->ps_mtx); } #endif /* COMPAT_43 */ @@ -444,6 +445,7 @@ freebsd4_sendsig(catcher, sig, mask, code) p = td->td_proc; PROC_LOCK_ASSERT(p, MA_OWNED); psp = p->p_sigacts; + mtx_assert(&psp->ps_mtx, MA_OWNED); regs = td->td_frame; oonstack = sigonstack(regs->tf_esp); @@ -467,7 +469,6 @@ freebsd4_sendsig(catcher, sig, mask, code) #endif } else sfp = (struct sigframe4 *)regs->tf_esp - 1; - PROC_UNLOCK(p); /* Translate the signal if appropriate. */ if (p->p_sysent->sv_sigtbl && sig <= p->p_sysent->sv_sigsize) @@ -476,8 +477,7 @@ freebsd4_sendsig(catcher, sig, mask, code) /* Build the argument list for the signal handler. */ sf.sf_signum = sig; sf.sf_ucontext = (register_t)&sfp->sf_uc; - PROC_LOCK(p); - if (SIGISMEMBER(p->p_sigacts->ps_siginfo, sig)) { + if (SIGISMEMBER(psp->ps_siginfo, sig)) { /* Signal handler installed with SA_SIGINFO. */ sf.sf_siginfo = (register_t)&sfp->sf_si; sf.sf_ahu.sf_action = (__siginfohandler_t *)catcher; @@ -492,6 +492,7 @@ freebsd4_sendsig(catcher, sig, mask, code) sf.sf_addr = regs->tf_err; sf.sf_ahu.sf_handler = catcher; } + mtx_unlock(&psp->ps_mtx); PROC_UNLOCK(p); /* @@ -543,6 +544,7 @@ freebsd4_sendsig(catcher, sig, mask, code) regs->tf_fs = _udatasel; regs->tf_ss = _udatasel; PROC_LOCK(p); + mtx_lock(&psp->ps_mtx); } #endif /* COMPAT_FREEBSD4 */ @@ -565,6 +567,7 @@ sendsig(catcher, sig, mask, code) p = td->td_proc; PROC_LOCK_ASSERT(p, MA_OWNED); psp = p->p_sigacts; + mtx_assert(&psp->ps_mtx,.MA_OWNED); #ifdef COMPAT_FREEBSD4 if (SIGISMEMBER(psp->ps_freebsd4, sig)) { freebsd4_sendsig(catcher, sig, mask, code); @@ -605,7 +608,6 @@ sendsig(catcher, sig, mask, code) sp = (char *)regs->tf_esp - sizeof(struct sigframe); /* Align to 16 bytes. */ sfp = (struct sigframe *)((unsigned int)sp & ~0xF); - PROC_UNLOCK(p); /* Translate the signal if appropriate. */ if (p->p_sysent->sv_sigtbl && sig <= p->p_sysent->sv_sigsize) @@ -614,8 +616,7 @@ sendsig(catcher, sig, mask, code) /* Build the argument list for the signal handler. */ sf.sf_signum = sig; sf.sf_ucontext = (register_t)&sfp->sf_uc; - PROC_LOCK(p); - if (SIGISMEMBER(p->p_sigacts->ps_siginfo, sig)) { + if (SIGISMEMBER(psp->ps_siginfo, sig)) { /* Signal handler installed with SA_SIGINFO. */ sf.sf_siginfo = (register_t)&sfp->sf_si; sf.sf_ahu.sf_action = (__siginfohandler_t *)catcher; @@ -630,6 +631,7 @@ sendsig(catcher, sig, mask, code) sf.sf_addr = regs->tf_err; sf.sf_ahu.sf_handler = catcher; } + mtx_unlock(&psp->ps_mtx); PROC_UNLOCK(p); /* @@ -681,6 +683,7 @@ sendsig(catcher, sig, mask, code) regs->tf_fs = _udatasel; regs->tf_ss = _udatasel; PROC_LOCK(p); + mtx_lock(&psp->ps_mtx); } /* diff --git a/sys/powerpc/aim/machdep.c b/sys/powerpc/aim/machdep.c index 81fb604a8b2f..62e46e91e2ef 100644 --- a/sys/powerpc/aim/machdep.c +++ b/sys/powerpc/aim/machdep.c @@ -408,7 +408,9 @@ sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code) td = curthread; p = td->td_proc; + PROC_LOCK_ASSERT(p, MA_OWNED); psp = p->p_sigacts; + mtx_assert(&psp->ps_mtx, MA_OWNED); tf = td->td_frame; oonstack = sigonstack(tf->fixreg[1]); @@ -439,7 +441,6 @@ sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code) } else { sfp = (struct sigframe *)(tf->fixreg[1] - rndfsize); } - PROC_UNLOCK(p); /* * Translate the signal if appropriate (Linux emu ?) @@ -466,9 +467,7 @@ sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code) tf->fixreg[1] = (register_t)sfp; tf->fixreg[FIRSTARG] = sig; tf->fixreg[FIRSTARG+2] = (register_t)&sfp->sf_uc; - - PROC_LOCK(p); - if (SIGISMEMBER(p->p_sigacts->ps_siginfo, sig)) { + if (SIGISMEMBER(psp->ps_siginfo, sig)) { /* * Signal handler installed with SA_SIGINFO. */ @@ -484,6 +483,7 @@ sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code) /* Old FreeBSD-style arguments. */ tf->fixreg[FIRSTARG+1] = code; } + mtx_unlock(&psp->ps_mtx); PROC_UNLOCK(p); tf->srr0 = (register_t)(PS_STRINGS - *(p->p_sysent->sv_szsigcode)); @@ -504,6 +504,7 @@ sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code) tf->srr0, tf->fixreg[1]); PROC_LOCK(p); + mtx_lock(&psp->ps_mtx); } int diff --git a/sys/powerpc/powerpc/machdep.c b/sys/powerpc/powerpc/machdep.c index 81fb604a8b2f..62e46e91e2ef 100644 --- a/sys/powerpc/powerpc/machdep.c +++ b/sys/powerpc/powerpc/machdep.c @@ -408,7 +408,9 @@ sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code) td = curthread; p = td->td_proc; + PROC_LOCK_ASSERT(p, MA_OWNED); psp = p->p_sigacts; + mtx_assert(&psp->ps_mtx, MA_OWNED); tf = td->td_frame; oonstack = sigonstack(tf->fixreg[1]); @@ -439,7 +441,6 @@ sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code) } else { sfp = (struct sigframe *)(tf->fixreg[1] - rndfsize); } - PROC_UNLOCK(p); /* * Translate the signal if appropriate (Linux emu ?) @@ -466,9 +467,7 @@ sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code) tf->fixreg[1] = (register_t)sfp; tf->fixreg[FIRSTARG] = sig; tf->fixreg[FIRSTARG+2] = (register_t)&sfp->sf_uc; - - PROC_LOCK(p); - if (SIGISMEMBER(p->p_sigacts->ps_siginfo, sig)) { + if (SIGISMEMBER(psp->ps_siginfo, sig)) { /* * Signal handler installed with SA_SIGINFO. */ @@ -484,6 +483,7 @@ sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code) /* Old FreeBSD-style arguments. */ tf->fixreg[FIRSTARG+1] = code; } + mtx_unlock(&psp->ps_mtx); PROC_UNLOCK(p); tf->srr0 = (register_t)(PS_STRINGS - *(p->p_sysent->sv_szsigcode)); @@ -504,6 +504,7 @@ sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code) tf->srr0, tf->fixreg[1]); PROC_LOCK(p); + mtx_lock(&psp->ps_mtx); } int diff --git a/sys/sparc64/sparc64/machdep.c b/sys/sparc64/sparc64/machdep.c index 6cf0f6af2df8..669f4c7b30f5 100644 --- a/sys/sparc64/sparc64/machdep.c +++ b/sys/sparc64/sparc64/machdep.c @@ -403,7 +403,9 @@ sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code) oonstack = 0; td = curthread; p = td->td_proc; + PROC_LOCK_ASSERT(p, MA_OWNED); psp = p->p_sigacts; + mtx_assert(&psp->ps_mtx, MA_OWNED); tf = td->td_frame; sp = tf->tf_sp + SPOFF; oonstack = sigonstack(sp); @@ -437,6 +439,7 @@ sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code) p->p_sigstk.ss_size - sizeof(struct sigframe)); } else sfp = (struct sigframe *)sp - 1; + mtx_unlock(&psp->ps_mtx); PROC_UNLOCK(p); fp = (struct frame *)sfp - 1; @@ -476,6 +479,7 @@ sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code) tf->tf_sp); PROC_LOCK(p); + mtx_lock(&psp->ps_mtx); } #ifndef _SYS_SYSPROTO_H_ diff --git a/sys/sys/proc.h b/sys/sys/proc.h index 92f97396287a..1b7982c11858 100644 --- a/sys/sys/proc.h +++ b/sys/sys/proc.h @@ -102,18 +102,6 @@ struct pgrp { struct mtx pg_mtx; /* Mutex to protect members */ }; -struct procsig { - sigset_t ps_sigignore; /* Signals being ignored. */ - sigset_t ps_sigcatch; /* Signals being caught by user. */ - int ps_flag; - struct sigacts *ps_sigacts; /* Signal actions, state. */ - int ps_refcnt; -}; - -#define PS_NOCLDWAIT 0x0001 /* No zombies if child dies */ -#define PS_NOCLDSTOP 0x0002 /* No SIGCHLD when children stop. */ -#define PS_CLDSIGIGN 0x0004 /* The SIGCHLD handler is SIG_IGN. */ - /* * pargs, used to hold a copy of the command line, if it had a sane length. */ @@ -157,6 +145,7 @@ struct pargs { * o - ktrace lock * p - select lock (sellock) * r - p_peers lock + * x - created at fork, only changes during single threading in exec * z - zombie threads/kse/ksegroup lock * * If the locking key specifies two identifiers (for example, p_pptr) then @@ -525,7 +514,7 @@ struct proc { struct pstats *p_stats; /* (b) Accounting/statistics (CPU). */ struct plimit *p_limit; /* (c*) Process limits. */ struct vm_object *p_upages_obj; /* (a) Upages object. */ - struct procsig *p_procsig; /* (c) Signal actions, state (CPU). */ + struct sigacts *p_sigacts; /* (x) Signal actions, state (CPU). */ /*struct ksegrp p_ksegrp; struct kse p_kse; */ @@ -614,9 +603,6 @@ struct proc { }; #define p_rlimit p_limit->pl_rlimit -#define p_sigacts p_procsig->ps_sigacts -#define p_sigignore p_procsig->ps_sigignore -#define p_sigcatch p_procsig->ps_sigcatch #define p_session p_pgrp->pg_session #define p_pgid p_pgrp->pg_id diff --git a/sys/sys/signalvar.h b/sys/sys/signalvar.h index 1173d7836c75..5635ab2a4e6c 100644 --- a/sys/sys/signalvar.h +++ b/sys/sys/signalvar.h @@ -37,6 +37,8 @@ #ifndef _SYS_SIGNALVAR_H_ #define _SYS_SIGNALVAR_H_ +#include <sys/_lock.h> +#include <sys/_mutex.h> #include <sys/signal.h> /* @@ -45,8 +47,11 @@ */ /* - * Process signal actions and state, needed only within the process - * (not necessarily resident). + * Logical process signal actions and state, needed only within the process + * The mapping between sigacts and proc structures is 1:1 except for rfork() + * processes masquerading as threads which use one structure for the whole + * group. All members are locked by the included mutex. The reference count + * and mutex must be last for the bcopy in sigacts_copy() to work. */ struct sigacts { sig_t ps_sigact[_SIG_MAXSIG]; /* Disposition of signals. */ @@ -56,11 +61,20 @@ struct sigacts { sigset_t ps_sigreset; /* Signals that reset when caught. */ sigset_t ps_signodefer; /* Signals not masked while handled. */ sigset_t ps_siginfo; /* Signals that want SA_SIGINFO args. */ - sigset_t ps_freebsd4; /* Signals using freebsd4 ucontext. */ + sigset_t ps_sigignore; /* Signals being ignored. */ + sigset_t ps_sigcatch; /* Signals being caught by user. */ + sigset_t ps_freebsd4; /* signals using freebsd4 ucontext. */ sigset_t ps_osigset; /* Signals using <= 3.x osigset_t. */ - sigset_t ps_usertramp; /* SunOS compat; libc sigtramp XXX. */ + sigset_t ps_usertramp; /* SunOS compat; libc sigtramp. XXX */ + int ps_flag; + int ps_refcnt; + struct mtx ps_mtx; }; +#define PS_NOCLDWAIT 0x0001 /* No zombies if child dies */ +#define PS_NOCLDSTOP 0x0002 /* No SIGCHLD when children stop. */ +#define PS_CLDSIGIGN 0x0004 /* The SIGCHLD handler is SIG_IGN. */ + #if defined(_KERNEL) && defined(COMPAT_43) /* * Compatibility. @@ -243,6 +257,11 @@ void pgsigio(struct sigio **, int signum, int checkctty); void pgsignal(struct pgrp *pgrp, int sig, int checkctty); void postsig(int sig); void psignal(struct proc *p, int sig); +struct sigacts *sigacts_alloc(void); +void sigacts_copy(struct sigacts *dest, struct sigacts *src); +void sigacts_free(struct sigacts *ps); +struct sigacts *sigacts_hold(struct sigacts *ps); +int sigacts_shared(struct sigacts *ps); void sigexit(struct thread *td, int signum) __dead2; int sig_ffs(sigset_t *set); void siginit(struct proc *p); diff --git a/sys/sys/user.h b/sys/sys/user.h index 473480aed5f3..a52610f2680f 100644 --- a/sys/sys/user.h +++ b/sys/sys/user.h @@ -174,7 +174,6 @@ void fill_kinfo_proc(struct proc *, struct kinfo_proc *); * when the process isn't running (esp. when swapped out). */ struct user { - struct sigacts u_sigacts; /* *p_sigacts */ struct pstats u_stats; /* *p_stats */ /* * Remaining field for a.out core dumps - not valid at other times! diff --git a/sys/vm/vm_glue.c b/sys/vm/vm_glue.c index cd00c3345c26..3c42ccae5e72 100644 --- a/sys/vm/vm_glue.c +++ b/sys/vm/vm_glue.c @@ -441,23 +441,14 @@ vm_forkproc(td, p2, td2, flags) /* XXXKSE this is unsatisfactory but should be adequate */ up = p2->p_uarea; + MPASS(p2->p_sigacts != NULL); /* * p_stats currently points at fields in the user struct * but not at &u, instead at p_addr. Copy parts of * p_stats; zero the rest of p_stats (statistics). - * - * If procsig->ps_refcnt is 1 and p2->p_sigacts is NULL we dont' need - * to share sigacts, so we use the up->u_sigacts. */ p2->p_stats = &up->u_stats; - if (p2->p_sigacts == NULL) { - if (p2->p_procsig->ps_refcnt != 1) - printf ("PID:%d NULL sigacts with refcnt not 1!\n",p2->p_pid); - p2->p_sigacts = &up->u_sigacts; - up->u_sigacts = *p1->p_sigacts; - } - bzero(&up->u_stats.pstat_startzero, (unsigned) ((caddr_t) &up->u_stats.pstat_endzero - (caddr_t) &up->u_stats.pstat_startzero)); @@ -465,7 +456,6 @@ vm_forkproc(td, p2, td2, flags) ((caddr_t) &up->u_stats.pstat_endcopy - (caddr_t) &up->u_stats.pstat_startcopy)); - /* * cpu_fork will copy and update the pcb, set up the kernel stack, * and make the child ready to run.