Index: kern/kern_fork.c
===================================================================
RCS file: /cvsroot/src/sys/kern/kern_fork.c,v
retrieving revision 1.185
diff -u -u -r1.185 kern_fork.c
--- kern/kern_fork.c	23 Aug 2011 13:01:25 -0000	1.185
+++ kern/kern_fork.c	1 Sep 2011 23:02:17 -0000
@@ -92,6 +92,7 @@
 #include <sys/syscallargs.h>
 #include <sys/uidinfo.h>
 #include <sys/sdt.h>
+#include <sys/ptrace.h>
 
 #include <uvm/uvm_extern.h>
 
@@ -458,6 +459,36 @@
 	LIST_INSERT_HEAD(&parent->p_children, p2, p_sibling);
 	p2->p_exitsig = exitsig;		/* signal for parent on exit */
 
+	if ((p1->p_slflag & (PSL_TRACEFORK|PSL_TRACED)) ==
+	    (PSL_TRACEFORK|PSL_TRACED)) {
+		p2->p_slflag |= PSL_TRACED;
+		p2->p_opptr = p2->p_pptr;
+printf("p2=%d pp2=%d p1=%d pp1=%d\n", p2->p_pid, p1->p_pid,
+    p2->p_pptr->p_pid, p1->p_pptr->p_pid);
+		if (p2->p_pptr != p1->p_pptr) {
+			struct proc *parent1 = p2->p_pptr;
+
+			if (parent1->p_lock < p2->p_lock) {
+				if (!mutex_tryenter(parent1->p_lock)) {
+					mutex_exit(p2->p_lock);
+					mutex_enter(parent1->p_lock);
+				}
+			} else if (parent1->p_lock > p2->p_lock) {
+				mutex_enter(parent1->p_lock);
+			}
+			parent1->p_slflag |= PSL_CHTRACED;
+			proc_reparent(p2, p1->p_pptr);
+			if (parent1->p_lock != p2->p_lock)
+				mutex_exit(parent1->p_lock);
+		}
+
+		/*
+		 * Set ptrace status.
+		 */
+		p1->p_fpid = p2->p_pid;
+		p2->p_fpid = p1->p_pid;
+	}
+
 	LIST_INSERT_AFTER(p1, p2, p_pglist);
 	LIST_INSERT_HEAD(&allproc, p2, p_list);
 
@@ -537,6 +568,13 @@
 	 */
 	while (p2->p_lflag & PL_PPWAIT)
 		cv_wait(&p1->p_waitcv, proc_lock);
+      
+        /*      
+         * If we're tracing the child, alert the parent too.
+         */     
+	if ((p1->p_slflag & (PSL_TRACEFORK|PSL_TRACED)) ==
+	    (PSL_TRACEFORK|PSL_TRACED))
+                psignal(p1, SIGSTOP);
 
 	mutex_exit(proc_lock);
 
Index: kern/sys_process.c
===================================================================
RCS file: /cvsroot/src/sys/kern/sys_process.c,v
retrieving revision 1.160
diff -u -u -r1.160 sys_process.c
--- kern/sys_process.c	31 Aug 2011 22:58:39 -0000	1.160
+++ kern/sys_process.c	1 Sep 2011 23:02:18 -0000
@@ -175,6 +175,9 @@
 #ifdef PT_SETFPREGS
 	case PT_SETFPREGS:
 #endif
+	case  PT_SET_EVENT_MASK:
+	case  PT_GET_EVENT_MASK:
+	case  PT_GET_PROCESS_STATE:
 #ifdef __HAVE_PTRACE_MACHDEP
 	PTRACE_MACHDEP_REQUEST_CASES
 #endif
@@ -236,6 +239,8 @@
 	struct uio uio;
 	struct iovec iov;
 	struct ptrace_io_desc piod;
+	struct ptrace_event pe;
+	struct ptrace_state ps;
 	struct ptrace_lwpinfo pl;
 	struct vmspace *vm;
 	int error, write, tmp, req, pheld;
@@ -376,6 +381,9 @@
 #ifdef PT_STEP
 	case  PT_STEP:
 #endif
+	case  PT_SET_EVENT_MASK:
+	case  PT_GET_EVENT_MASK:
+	case  PT_GET_PROCESS_STATE:
 		/*
 		 * You can't do what you want to the process if:
 		 *	(1) It's not being traced at all,
@@ -698,6 +706,7 @@
 			t->p_opptr = NULL;
 		}
 	sendsig:
+		t->p_fpid = 0;
 		/* Finally, deliver the requested signal (or none). */
 		if (t->p_stat == SSTOP) {
 			/*
@@ -760,6 +769,37 @@
 		signo = SIGSTOP;
 		goto sendsig;
 
+	case  PT_GET_EVENT_MASK:
+		if (SCARG(uap, data) != sizeof(pe))
+			return EINVAL;
+		memset(&pe, 0, sizeof(pe));
+		pe.pe_set_event = ISSET(t->p_slflag, PSL_TRACEFORK) ? 
+			PTRACE_FORK : 0;
+		error = copyout(&pe, SCARG(uap, addr), sizeof(pe));
+		break;
+
+	case  PT_SET_EVENT_MASK:
+		if (SCARG(uap, data) != sizeof(pe))
+			return EINVAL;
+		if ((error = copyin(SCARG(uap, addr), &pe, sizeof(pe))) != 0)
+			return error;
+		if (pe.pe_set_event & PTRACE_FORK)
+			SET(t->p_slflag, PSL_TRACEFORK);
+		else
+			CLR(t->p_slflag, PSL_TRACEFORK);
+		break;
+
+	case  PT_GET_PROCESS_STATE:
+		if (SCARG(uap, data) != sizeof(ps))
+			return EINVAL;
+		memset(&ps, 0, sizeof(ps));
+		if (t->p_fpid) {
+			ps.pe_report_event = PTRACE_FORK;
+			ps.pe_other_pid = t->p_fpid;
+		}
+		error = copyout(&ps, SCARG(uap, addr), sizeof(ps));
+		break;
+
 	case PT_LWPINFO:
 		if (SCARG(uap, data) != sizeof(pl)) {
 			error = EINVAL;
Index: sys/proc.h
===================================================================
RCS file: /cvsroot/src/sys/sys/proc.h,v
retrieving revision 1.309
diff -u -u -r1.309 proc.h
--- sys/proc.h	31 Aug 2011 22:58:39 -0000	1.309
+++ sys/proc.h	1 Sep 2011 23:02:19 -0000
@@ -290,6 +290,7 @@
 	sigpend_t	p_sigpend;	/* p: pending signals */
 	struct lcproc	*p_lwpctl;	/* p, a: _lwp_ctl() information */
 	pid_t		p_ppid;		/* :: cached parent pid */
+	pid_t 		p_fpid;		/* :: forked pid */
 
 /*
  * End area that is zeroed on creation
@@ -374,6 +375,7 @@
  * These flags are kept in p_sflag and are protected by the proc_lock
  * and p_lock.  Access from process context only.
  */
+#define	PSL_TRACEFORK	0x00000001 /* traced process wants fork events */
 #define	PSL_TRACED	0x00000800 /* Debugged process being traced */
 #define	PSL_FSTRACE	0x00010000 /* Debugger process being traced by procfs */
 #define	PSL_CHTRACED	0x00400000 /* Child has been traced & reparented */
Index: sys/ptrace.h
===================================================================
RCS file: /cvsroot/src/sys/sys/ptrace.h,v
retrieving revision 1.43
diff -u -u -r1.43 ptrace.h
--- sys/ptrace.h	31 Aug 2011 22:58:39 -0000	1.43
+++ sys/ptrace.h	1 Sep 2011 23:02:19 -0000
@@ -34,22 +34,60 @@
 #ifndef	_SYS_PTRACE_H_
 #define	_SYS_PTRACE_H_
 
-#define	PT_TRACE_ME	0	/* child declares it's being traced */
-#define	PT_READ_I	1	/* read word in child's I space */
-#define	PT_READ_D	2	/* read word in child's D space */
-#define	PT_WRITE_I	4	/* write word in child's I space */
-#define	PT_WRITE_D	5	/* write word in child's D space */
-#define	PT_CONTINUE	7	/* continue the child */
-#define	PT_KILL		8	/* kill the child process */
-#define	PT_ATTACH	9	/* attach to running process */
-#define	PT_DETACH	10	/* detach from running process */
-#define	PT_IO		11	/* do I/O to/from the stopped process */
-#define	PT_DUMPCORE	12	/* make the child generate a core dump */
-#define	PT_LWPINFO	13	/* get info about the LWP */
-#define	PT_SYSCALL	14	/* stop on syscall entry/exit */
-#define	PT_SYSCALLEMU	15	/* cancel syscall, tracer will emulate it */
-#define	PT_FIRSTMACH	32	/* for machine-specific requests */
-#include <machine/ptrace.h>	/* machine-specific requests, if any */
+#define	PT_TRACE_ME		0	/* child declares it's being traced */
+#define	PT_READ_I		1	/* read word in child's I space */
+#define	PT_READ_D		2	/* read word in child's D space */
+#define	PT_WRITE_I		4	/* write word in child's I space */
+#define	PT_WRITE_D		5	/* write word in child's D space */
+#define	PT_CONTINUE		7	/* continue the child */
+#define	PT_KILL			8	/* kill the child process */
+#define	PT_ATTACH		9	/* attach to running process */
+#define	PT_DETACH		10	/* detach from running process */
+#define	PT_IO			11	/* do I/O to/from the stopped process */
+#define	PT_DUMPCORE		12	/* make child generate a core dump */
+#define	PT_LWPINFO		13	/* get info about the LWP */
+#define	PT_SYSCALL		14	/* stop on syscall entry/exit */
+#define	PT_SYSCALLEMU		15	/* cancel syscall, tracer emulates it */
+#define	PT_SET_EVENT_MASK	16	/* set the event mask, defined below */
+#define	PT_GET_EVENT_MASK	17	/* get the event mask, defined below */
+#define	PT_GET_PROCESS_STATE	18	/* get process state, defined below */
+
+#define	PT_FIRSTMACH		32	/* for machine-specific requests */
+#include <machine/ptrace.h>		/* machine-specific requests, if any */
+
+#define PT_STRINGS \
+/*  0 */    "PT_TRACE_ME", \
+/*  1 */    "PT_READ_I", \
+/*  2 */    "PT_READ_D", \
+/*  3 */    "*PT_INVALID_3*", \
+/*  4 */    "PT_WRITE_I", \
+/*  5 */    "PT_WRITE_D", \
+/*  6 */    "*PT_INVALID_6*", \
+/*  7 */    "PT_CONTINUE", \
+/*  8 */    "PT_KILL", \
+/*  9 */    "PT_ATTACH", \
+/* 10 */    "PT_DETACH", \
+/* 11 */    "PT_IO", \
+/* 12 */    "PT_DUMPCORE", \
+/* 13 */    "PT_LWPINFO", \
+/* 14 */    "PT_SYSCALL", \
+/* 15 */    "PT_SYSCALLEMU", \
+/* 16 */    "PT_SET_EVENT_MASK", \
+/* 17 */    "PT_GET_EVENT_MASK", \
+/* 18 */    "PT_GET_PROCESS_STATE",
+
+/* PT_{G,S}EVENT_MASK */
+typedef struct ptrace_event {
+	int	pe_set_event;
+} ptrace_event_t;
+
+/* PT_GET_PROCESS_STATE */
+typedef struct ptrace_state {
+	int	pe_report_event;
+	pid_t	pe_other_pid;
+} ptrace_state_t;
+
+#define	PTRACE_FORK	0x0001	/* Report forks */
 
 /*
  * Argument structure for PT_IO.
Index: arch/x86/x86/syscall.c
===================================================================
RCS file: /cvsroot/src/sys/arch/x86/x86/syscall.c,v
retrieving revision 1.3
diff -u -u -r1.3 syscall.c
--- arch/x86/x86/syscall.c	21 Nov 2009 03:11:02 -0000	1.3
+++ arch/x86/x86/syscall.c	1 Sep 2011 23:02:19 -0000
@@ -67,6 +67,13 @@
 {
 	struct lwp *l = arg;
 	struct trapframe *tf = l->l_md.md_regs;
+	struct proc *p = l->l_proc;
+
+	if (p->p_slflag & PSL_TRACED) {
+		mutex_enter(proc_lock);
+		psignal(p, SIGSTOP);
+		mutex_exit(proc_lock);
+	}
 
 	X86_TF_RAX(tf) = 0;
 	X86_TF_RFLAGS(tf) &= ~PSL_C;