Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 7 Feb 2013 15:34:22 +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: r246484 - in head/sys: kern sys
Message-ID:  <201302071534.r17FYMew004229@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
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)



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201302071534.r17FYMew004229>