From owner-svn-src-head@FreeBSD.ORG Thu Feb 7 15:34:23 2013 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by hub.freebsd.org (Postfix) with ESMTP id 860CCEF2; Thu, 7 Feb 2013 15:34:23 +0000 (UTC) (envelope-from kib@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) by mx1.freebsd.org (Postfix) with ESMTP id 6D25488C; Thu, 7 Feb 2013 15:34:23 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.5/8.14.5) with ESMTP id r17FYN4N004237; Thu, 7 Feb 2013 15:34:23 GMT (envelope-from kib@svn.freebsd.org) Received: (from kib@localhost) by svn.freebsd.org (8.14.5/8.14.5/Submit) id r17FYMew004229; Thu, 7 Feb 2013 15:34:22 GMT (envelope-from kib@svn.freebsd.org) Message-Id: <201302071534.r17FYMew004229@svn.freebsd.org> From: Konstantin Belousov Date: Thu, 7 Feb 2013 15:34:22 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r246484 - in head/sys: kern sys X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 07 Feb 2013 15:34:23 -0000 Author: kib Date: Thu Feb 7 15:34:22 2013 New Revision: 246484 URL: http://svnweb.freebsd.org/changeset/base/246484 Log: When vforked child is traced, the debugging events are not generated until child performs exec(). The behaviour is reasonable when a debugger is the real parent, because the parent is stopped until exec(), and sending a debugging event to the debugger would deadlock both parent and child. On the other hand, when debugger is not the parent of the vforked child, not sending debugging signals makes it impossible to debug across vfork. Fix the issue by declining generating debug signals only when vfork() was done and child called ptrace(PT_TRACEME). Set a new process flag P_PPTRACE from the attach code for PT_TRACEME, if P_PPWAIT flag is set, which indicates that the process was created with vfork() and still did not execed. Check P_PPTRACE from issignal(), instead of refusing the trace outright for the P_PPWAIT case. The scope of P_PPTRACE is exactly contained in the scope of P_PPWAIT. Found and tested by: zont Reviewed by: pluknet MFC after: 2 weeks Modified: head/sys/kern/kern_exec.c head/sys/kern/kern_exit.c head/sys/kern/kern_sig.c head/sys/kern/sys_process.c head/sys/sys/proc.h Modified: head/sys/kern/kern_exec.c ============================================================================== --- head/sys/kern/kern_exec.c Thu Feb 7 15:22:50 2013 (r246483) +++ head/sys/kern/kern_exec.c Thu Feb 7 15:34:22 2013 (r246484) @@ -640,7 +640,7 @@ interpret: */ p->p_flag |= P_EXEC; if (p->p_pptr && (p->p_flag & P_PPWAIT)) { - p->p_flag &= ~P_PPWAIT; + p->p_flag &= ~(P_PPWAIT | P_PPTRACE); cv_broadcast(&p->p_pwait); } Modified: head/sys/kern/kern_exit.c ============================================================================== --- head/sys/kern/kern_exit.c Thu Feb 7 15:22:50 2013 (r246483) +++ head/sys/kern/kern_exit.c Thu Feb 7 15:34:22 2013 (r246484) @@ -266,7 +266,7 @@ exit1(struct thread *td, int rv) PROC_LOCK(p); rv = p->p_xstat; /* Event handler could change exit status */ stopprofclock(p); - p->p_flag &= ~(P_TRACED | P_PPWAIT); + p->p_flag &= ~(P_TRACED | P_PPWAIT | P_PPTRACE); /* * Stop the real interval timer. If the handler is currently Modified: head/sys/kern/kern_sig.c ============================================================================== --- head/sys/kern/kern_sig.c Thu Feb 7 15:22:50 2013 (r246483) +++ head/sys/kern/kern_sig.c Thu Feb 7 15:34:22 2013 (r246484) @@ -2618,7 +2618,7 @@ issignal(struct thread *td, int stop_all sigqueue_delete(&p->p_sigqueue, sig); continue; } - if (p->p_flag & P_TRACED && (p->p_flag & P_PPWAIT) == 0) { + if (p->p_flag & P_TRACED && (p->p_flag & P_PPTRACE) == 0) { /* * If traced, always stop. * Remove old signal from queue before the stop. Modified: head/sys/kern/sys_process.c ============================================================================== --- head/sys/kern/sys_process.c Thu Feb 7 15:22:50 2013 (r246483) +++ head/sys/kern/sys_process.c Thu Feb 7 15:34:22 2013 (r246484) @@ -822,6 +822,8 @@ kern_ptrace(struct thread *td, int req, case PT_TRACE_ME: /* set my trace flag and "owner" so it can read/write me */ p->p_flag |= P_TRACED; + if (p->p_flag & P_PPWAIT) + p->p_flag |= P_PPTRACE; p->p_oppid = p->p_pptr->p_pid; break; Modified: head/sys/sys/proc.h ============================================================================== --- head/sys/sys/proc.h Thu Feb 7 15:22:50 2013 (r246483) +++ head/sys/sys/proc.h Thu Feb 7 15:34:22 2013 (r246484) @@ -636,6 +636,7 @@ struct proc { #define P_INMEM 0x10000000 /* Loaded into memory. */ #define P_SWAPPINGOUT 0x20000000 /* Process is being swapped out. */ #define P_SWAPPINGIN 0x40000000 /* Process is being swapped in. */ +#define P_PPTRACE 0x80000000 /* PT_TRACEME by vforked child. */ #define P_STOPPED (P_STOPPED_SIG|P_STOPPED_SINGLE|P_STOPPED_TRACE) #define P_SHOULDSTOP(p) ((p)->p_flag & P_STOPPED)