Date: Fri, 30 Oct 2009 10:10:39 +0000 (UTC) From: Konstantin Belousov <kib@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r198670 - in head/sys: kern sys Message-ID: <200910301010.n9UAAdnm037867@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: kib Date: Fri Oct 30 10:10:39 2009 New Revision: 198670 URL: http://svn.freebsd.org/changeset/base/198670 Log: Trapsignal() and postsig() call kern_sigprocmask() with both process lock and curproc->p_sigacts->ps_mtx. Reschedule_signals may need to have ps_mtx locked to decide and wakeup a thread, causing recursion on the mutex. Inform kern_sigprocmask() and reschedule_signals() about lock state of the ps_mtx by new flag SIGPROCMASK_PS_LOCKED to avoid recursion. Reported and tested by: keramida MFC after: 1 month Modified: head/sys/kern/kern_sig.c head/sys/sys/signalvar.h Modified: head/sys/kern/kern_sig.c ============================================================================== --- head/sys/kern/kern_sig.c Fri Oct 30 08:53:11 2009 (r198669) +++ head/sys/kern/kern_sig.c Fri Oct 30 10:10:39 2009 (r198670) @@ -220,7 +220,7 @@ static int sigproptbl[NSIG] = { SA_KILL|SA_PROC, /* SIGUSR2 */ }; -static void reschedule_signals(struct proc *p, sigset_t block); +static void reschedule_signals(struct proc *p, sigset_t block, int flags); static void sigqueue_start(void) @@ -1024,7 +1024,7 @@ kern_sigprocmask(struct thread *td, int * possibly waking it up. */ if (p->p_numthreads != 1) - reschedule_signals(p, new_block); + reschedule_signals(p, new_block, flags); if (!(flags & SIGPROCMASK_PROC_LOCKED)) PROC_UNLOCK(p); @@ -1859,13 +1859,11 @@ trapsignal(struct thread *td, ksiginfo_t #endif (*p->p_sysent->sv_sendsig)(ps->ps_sigact[_SIG_IDX(sig)], ksi, &td->td_sigmask); - SIGSETOR(td->td_sigmask, ps->ps_catchmask[_SIG_IDX(sig)]); - if (!SIGISMEMBER(ps->ps_signodefer, sig)) { - SIGEMPTYSET(mask); + mask = ps->ps_catchmask[_SIG_IDX(sig)]; + if (!SIGISMEMBER(ps->ps_signodefer, sig)) SIGADDSET(mask, sig); - kern_sigprocmask(td, SIG_BLOCK, &mask, NULL, - SIGPROCMASK_PROC_LOCKED); - } + kern_sigprocmask(td, SIG_BLOCK, &mask, NULL, + SIGPROCMASK_PROC_LOCKED | SIGPROCMASK_PS_LOCKED); if (SIGISMEMBER(ps->ps_sigreset, sig)) { /* * See kern_sigaction() for origin of this code. @@ -2401,7 +2399,7 @@ stopme: } static void -reschedule_signals(struct proc *p, sigset_t block) +reschedule_signals(struct proc *p, sigset_t block, int flags) { struct sigacts *ps; struct thread *td; @@ -2419,12 +2417,14 @@ reschedule_signals(struct proc *p, sigse td = sigtd(p, i, 0); signotify(td); - mtx_lock(&ps->ps_mtx); + if (!(flags & SIGPROCMASK_PS_LOCKED)) + mtx_lock(&ps->ps_mtx); if (p->p_flag & P_TRACED || SIGISMEMBER(ps->ps_sigcatch, i)) tdsigwakeup(td, i, SIG_CATCH, (SIGISMEMBER(ps->ps_sigintr, i) ? EINTR : ERESTART)); - mtx_unlock(&ps->ps_mtx); + if (!(flags & SIGPROCMASK_PS_LOCKED)) + mtx_unlock(&ps->ps_mtx); } } @@ -2452,7 +2452,7 @@ tdsigcleanup(struct thread *td) SIGFILLSET(unblocked); SIGSETNAND(unblocked, td->td_sigmask); SIGFILLSET(td->td_sigmask); - reschedule_signals(p, unblocked); + reschedule_signals(p, unblocked, 0); } @@ -2734,15 +2734,11 @@ postsig(sig) } else returnmask = td->td_sigmask; - kern_sigprocmask(td, SIG_BLOCK, - &ps->ps_catchmask[_SIG_IDX(sig)], NULL, - SIGPROCMASK_PROC_LOCKED); - if (!SIGISMEMBER(ps->ps_signodefer, sig)) { - SIGEMPTYSET(mask); + mask = ps->ps_catchmask[_SIG_IDX(sig)]; + if (!SIGISMEMBER(ps->ps_signodefer, sig)) SIGADDSET(mask, sig); - kern_sigprocmask(td, SIG_BLOCK, &mask, NULL, - SIGPROCMASK_PROC_LOCKED); - } + kern_sigprocmask(td, SIG_BLOCK, &mask, NULL, + SIGPROCMASK_PROC_LOCKED | SIGPROCMASK_PS_LOCKED); if (SIGISMEMBER(ps->ps_sigreset, sig)) { /* Modified: head/sys/sys/signalvar.h ============================================================================== --- head/sys/sys/signalvar.h Fri Oct 30 08:53:11 2009 (r198669) +++ head/sys/sys/signalvar.h Fri Oct 30 10:10:39 2009 (r198670) @@ -319,6 +319,7 @@ extern int kern_logsigexit; /* Sysctl va /* flags for kern_sigprocmask */ #define SIGPROCMASK_OLD 0x0001 #define SIGPROCMASK_PROC_LOCKED 0x0002 +#define SIGPROCMASK_PS_LOCKED 0x0004 /* * Machine-independent functions:
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200910301010.n9UAAdnm037867>