From owner-svn-src-all@freebsd.org Mon Jul 18 10:53:48 2016 Return-Path: Delivered-To: svn-src-all@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id EE0C3B99FA9; Mon, 18 Jul 2016 10:53:48 +0000 (UTC) (envelope-from kib@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id A74C31CD6; Mon, 18 Jul 2016 10:53:48 +0000 (UTC) (envelope-from kib@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id u6IArlkh096492; Mon, 18 Jul 2016 10:53:47 GMT (envelope-from kib@FreeBSD.org) Received: (from kib@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id u6IArlUY096490; Mon, 18 Jul 2016 10:53:47 GMT (envelope-from kib@FreeBSD.org) Message-Id: <201607181053.u6IArlUY096490@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: kib set sender to kib@FreeBSD.org using -f From: Konstantin Belousov Date: Mon, 18 Jul 2016 10:53:47 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r302999 - head/sys/kern X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.22 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: Mon, 18 Jul 2016 10:53:49 -0000 Author: kib Date: Mon Jul 18 10:53:47 2016 New Revision: 302999 URL: https://svnweb.freebsd.org/changeset/base/302999 Log: The assertion re-added in r302614 was triggered when stopping signal is delivered to vforked child. Issue is that we avoid stopping such children in issignal() to not block parents. But executed AST, which ignored stops, leaves the child with the signal pending but no AST pending. On first exec after vfork(), call signotify() to handle pending reenabled signals. Adjust the assert to not check vfork children until exec. Reported and tested by: pho Sponsored by: The FreeBSD Foundation MFC after: 2 weeks Modified: head/sys/kern/kern_exec.c head/sys/kern/subr_trap.c Modified: head/sys/kern/kern_exec.c ============================================================================== --- head/sys/kern/kern_exec.c Mon Jul 18 09:29:08 2016 (r302998) +++ head/sys/kern/kern_exec.c Mon Jul 18 10:53:47 2016 (r302999) @@ -760,6 +760,8 @@ interpret: if (p->p_flag & P_PPWAIT) { p->p_flag &= ~(P_PPWAIT | P_PPTRACE); cv_broadcast(&p->p_pwait); + /* STOPs are no longer ignored, arrange for AST */ + signotify(td); } /* Modified: head/sys/kern/subr_trap.c ============================================================================== --- head/sys/kern/subr_trap.c Mon Jul 18 09:29:08 2016 (r302998) +++ head/sys/kern/subr_trap.c Mon Jul 18 10:53:47 2016 (r302999) @@ -107,15 +107,20 @@ userret(struct thread *td, struct trapfr * multi-threaded processes, where signal distribution might * change due to other threads changing sigmask, the check is * racy and cannot be performed reliably. + * If current process is vfork child, indicated by P_PPWAIT, then + * issignal() ignores stops, so we block the check to avoid + * classifying pending signals. */ if (p->p_numthreads == 1) { PROC_LOCK(p); thread_lock(td); - KASSERT(!SIGPENDING(td) || - (td->td_flags & (TDF_NEEDSIGCHK | TDF_ASTPENDING)) == - (TDF_NEEDSIGCHK | TDF_ASTPENDING), - ("failed to set signal flags for ast p %p td %p fl %x", - p, td, td->td_flags)); + if ((p->p_flag & P_PPWAIT) == 0) { + KASSERT(!SIGPENDING(td) || (td->td_flags & + (TDF_NEEDSIGCHK | TDF_ASTPENDING)) == + (TDF_NEEDSIGCHK | TDF_ASTPENDING), + ("failed to set signal flags for ast p %p " + "td %p fl %x", p, td, td->td_flags)); + } thread_unlock(td); PROC_UNLOCK(p); } @@ -281,12 +286,15 @@ ast(struct trapframe *framep) * td_flags, since signal might have been delivered * after we cleared td_flags above. This is one of * the reason for looping check for AST condition. + * See comment in userret() about P_PPWAIT. */ - KASSERT(!SIGPENDING(td) || - (td->td_flags & (TDF_NEEDSIGCHK | TDF_ASTPENDING)) == - (TDF_NEEDSIGCHK | TDF_ASTPENDING), - ("failed2 to set signal flags for ast p %p td %p fl %x %x", - p, td, flags, td->td_flags)); + if ((p->p_flag & P_PPWAIT) == 0) { + KASSERT(!SIGPENDING(td) || (td->td_flags & + (TDF_NEEDSIGCHK | TDF_ASTPENDING)) == + (TDF_NEEDSIGCHK | TDF_ASTPENDING), + ("failed2 to set signal flags for ast p %p td %p " + "fl %x %x", p, td, flags, td->td_flags)); + } thread_unlock(td); PROC_UNLOCK(p); }