From owner-svn-src-all@FreeBSD.ORG Fri Oct 30 10:10:39 2009 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id EF4B8106566B; Fri, 30 Oct 2009 10:10:39 +0000 (UTC) (envelope-from kib@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id DCFDA8FC1F; Fri, 30 Oct 2009 10:10:39 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id n9UAAdUM037870; Fri, 30 Oct 2009 10:10:39 GMT (envelope-from kib@svn.freebsd.org) Received: (from kib@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id n9UAAdnm037867; Fri, 30 Oct 2009 10:10:39 GMT (envelope-from kib@svn.freebsd.org) Message-Id: <200910301010.n9UAAdnm037867@svn.freebsd.org> From: Konstantin Belousov Date: Fri, 30 Oct 2009 10:10:39 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r198670 - in head/sys: kern sys X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 30 Oct 2009 10:10:40 -0000 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: