Index: stable/11/sys/kern/kern_exit.c
===================================================================
--- stable/11/sys/kern/kern_exit.c	(revision 346540)
+++ stable/11/sys/kern/kern_exit.c	(revision 346541)
@@ -1,1357 +1,1362 @@
 /*-
  * Copyright (c) 1982, 1986, 1989, 1991, 1993
  *	The Regents of the University of California.  All rights reserved.
  * (c) UNIX System Laboratories, Inc.
  * All or some portions of this file are derived from material licensed
  * to the University of California by American Telephone and Telegraph
  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
  * the permission of UNIX System Laboratories, Inc.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  * 4. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
  *	@(#)kern_exit.c	8.7 (Berkeley) 2/12/94
  */
 
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
 #include "opt_compat.h"
 #include "opt_ktrace.h"
 
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/sysproto.h>
 #include <sys/capsicum.h>
 #include <sys/eventhandler.h>
 #include <sys/kernel.h>
 #include <sys/malloc.h>
 #include <sys/lock.h>
 #include <sys/mutex.h>
 #include <sys/proc.h>
 #include <sys/procdesc.h>
 #include <sys/pioctl.h>
 #include <sys/jail.h>
 #include <sys/tty.h>
 #include <sys/wait.h>
 #include <sys/vmmeter.h>
 #include <sys/vnode.h>
 #include <sys/racct.h>
 #include <sys/resourcevar.h>
 #include <sys/sbuf.h>
 #include <sys/signalvar.h>
 #include <sys/sched.h>
 #include <sys/sx.h>
 #include <sys/syscallsubr.h>
 #include <sys/syslog.h>
 #include <sys/ptrace.h>
 #include <sys/acct.h>		/* for acct_process() function prototype */
 #include <sys/filedesc.h>
 #include <sys/sdt.h>
 #include <sys/shm.h>
 #include <sys/sem.h>
 #include <sys/umtx.h>
 #ifdef KTRACE
 #include <sys/ktrace.h>
 #endif
 
 #include <security/audit/audit.h>
 #include <security/mac/mac_framework.h>
 
 #include <vm/vm.h>
 #include <vm/vm_extern.h>
 #include <vm/vm_param.h>
 #include <vm/pmap.h>
 #include <vm/vm_map.h>
 #include <vm/vm_page.h>
 #include <vm/uma.h>
 #include <vm/vm_domain.h>
 
 #ifdef KDTRACE_HOOKS
 #include <sys/dtrace_bsd.h>
 dtrace_execexit_func_t	dtrace_fasttrap_exit;
 #endif
 
 SDT_PROVIDER_DECLARE(proc);
 SDT_PROBE_DEFINE1(proc, , , exit, "int");
 
 /* Hook for NFS teardown procedure. */
 void (*nlminfo_release_p)(struct proc *p);
 
 EVENTHANDLER_LIST_DECLARE(process_exit);
 
 struct proc *
 proc_realparent(struct proc *child)
 {
 	struct proc *p, *parent;
 
 	sx_assert(&proctree_lock, SX_LOCKED);
 	if ((child->p_treeflag & P_TREE_ORPHANED) == 0) {
 		if (child->p_oppid == 0 ||
 		    child->p_pptr->p_pid == child->p_oppid)
 			parent = child->p_pptr;
 		else
 			parent = initproc;
 		return (parent);
 	}
 	for (p = child; (p->p_treeflag & P_TREE_FIRST_ORPHAN) == 0;) {
 		/* Cannot use LIST_PREV(), since the list head is not known. */
 		p = __containerof(p->p_orphan.le_prev, struct proc,
 		    p_orphan.le_next);
 		KASSERT((p->p_treeflag & P_TREE_ORPHANED) != 0,
 		    ("missing P_ORPHAN %p", p));
 	}
 	parent = __containerof(p->p_orphan.le_prev, struct proc,
 	    p_orphans.lh_first);
 	return (parent);
 }
 
 void
 reaper_abandon_children(struct proc *p, bool exiting)
 {
 	struct proc *p1, *p2, *ptmp;
 
 	sx_assert(&proctree_lock, SX_LOCKED);
 	KASSERT(p != initproc, ("reaper_abandon_children for initproc"));
 	if ((p->p_treeflag & P_TREE_REAPER) == 0)
 		return;
 	p1 = p->p_reaper;
 	LIST_FOREACH_SAFE(p2, &p->p_reaplist, p_reapsibling, ptmp) {
 		LIST_REMOVE(p2, p_reapsibling);
 		p2->p_reaper = p1;
 		p2->p_reapsubtree = p->p_reapsubtree;
 		LIST_INSERT_HEAD(&p1->p_reaplist, p2, p_reapsibling);
 		if (exiting && p2->p_pptr == p) {
 			PROC_LOCK(p2);
 			proc_reparent(p2, p1);
 			PROC_UNLOCK(p2);
 		}
 	}
 	KASSERT(LIST_EMPTY(&p->p_reaplist), ("p_reaplist not empty"));
 	p->p_treeflag &= ~P_TREE_REAPER;
 }
 
 static void
 clear_orphan(struct proc *p)
 {
 	struct proc *p1;
 
 	sx_assert(&proctree_lock, SA_XLOCKED);
 	if ((p->p_treeflag & P_TREE_ORPHANED) == 0)
 		return;
 	if ((p->p_treeflag & P_TREE_FIRST_ORPHAN) != 0) {
 		p1 = LIST_NEXT(p, p_orphan);
 		if (p1 != NULL)
 			p1->p_treeflag |= P_TREE_FIRST_ORPHAN;
 		p->p_treeflag &= ~P_TREE_FIRST_ORPHAN;
 	}
 	LIST_REMOVE(p, p_orphan);
 	p->p_treeflag &= ~P_TREE_ORPHANED;
 }
 
 /*
  * exit -- death of process.
  */
 void
 sys_sys_exit(struct thread *td, struct sys_exit_args *uap)
 {
 
 	exit1(td, uap->rval, 0);
 	/* NOTREACHED */
 }
 
 /*
  * Exit: deallocate address space and other resources, change proc state to
  * zombie, and unlink proc from allproc and parent's lists.  Save exit status
  * and rusage for wait().  Check for child processes and orphan them.
  */
 void
 exit1(struct thread *td, int rval, int signo)
 {
 	struct proc *p, *nq, *q, *t;
 	struct thread *tdt;
 	ksiginfo_t *ksi, *ksi1;
 
 	mtx_assert(&Giant, MA_NOTOWNED);
 	KASSERT(rval == 0 || signo == 0, ("exit1 rv %d sig %d", rval, signo));
 
 	p = td->td_proc;
 	/*
 	 * XXX in case we're rebooting we just let init die in order to
 	 * work around an unsolved stack overflow seen very late during
 	 * shutdown on sparc64 when the gmirror worker process exists.
 	 */
 	if (p == initproc && rebooting == 0) {
 		printf("init died (signal %d, exit %d)\n", signo, rval);
 		panic("Going nowhere without my init!");
 	}
 
 	/*
 	 * Deref SU mp, since the thread does not return to userspace.
 	 */
 	td_softdep_cleanup(td);
 
 	/*
 	 * MUST abort all other threads before proceeding past here.
 	 */
 	PROC_LOCK(p);
 	/*
 	 * First check if some other thread or external request got
 	 * here before us.  If so, act appropriately: exit or suspend.
 	 * We must ensure that stop requests are handled before we set
 	 * P_WEXIT.
 	 */
 	thread_suspend_check(0);
 	while (p->p_flag & P_HADTHREADS) {
 		/*
 		 * Kill off the other threads. This requires
 		 * some co-operation from other parts of the kernel
 		 * so it may not be instantaneous.  With this state set
 		 * any thread entering the kernel from userspace will
 		 * thread_exit() in trap().  Any thread attempting to
 		 * sleep will return immediately with EINTR or EWOULDBLOCK
 		 * which will hopefully force them to back out to userland
 		 * freeing resources as they go.  Any thread attempting
 		 * to return to userland will thread_exit() from userret().
 		 * thread_exit() will unsuspend us when the last of the
 		 * other threads exits.
 		 * If there is already a thread singler after resumption,
 		 * calling thread_single will fail; in that case, we just
 		 * re-check all suspension request, the thread should
 		 * either be suspended there or exit.
 		 */
 		if (!thread_single(p, SINGLE_EXIT))
 			/*
 			 * All other activity in this process is now
 			 * stopped.  Threading support has been turned
 			 * off.
 			 */
 			break;
 		/*
 		 * Recheck for new stop or suspend requests which
 		 * might appear while process lock was dropped in
 		 * thread_single().
 		 */
 		thread_suspend_check(0);
 	}
 	KASSERT(p->p_numthreads == 1,
 	    ("exit1: proc %p exiting with %d threads", p, p->p_numthreads));
 	racct_sub(p, RACCT_NTHR, 1);
 
 	/* Let event handler change exit status */
 	p->p_xexit = rval;
 	p->p_xsig = signo;
 
 	/*
 	 * Wakeup anyone in procfs' PIOCWAIT.  They should have a hold
 	 * on our vmspace, so we should block below until they have
 	 * released their reference to us.  Note that if they have
 	 * requested S_EXIT stops we will block here until they ack
 	 * via PIOCCONT.
 	 */
 	_STOPEVENT(p, S_EXIT, 0);
 
 	/*
 	 * Ignore any pending request to stop due to a stop signal.
 	 * Once P_WEXIT is set, future requests will be ignored as
 	 * well.
 	 */
 	p->p_flag &= ~P_STOPPED_SIG;
 	KASSERT(!P_SHOULDSTOP(p), ("exiting process is stopped"));
 
 	/*
 	 * Note that we are exiting and do another wakeup of anyone in
 	 * PIOCWAIT in case they aren't listening for S_EXIT stops or
 	 * decided to wait again after we told them we are exiting.
 	 */
 	p->p_flag |= P_WEXIT;
 	wakeup(&p->p_stype);
 
 	/*
 	 * Wait for any processes that have a hold on our vmspace to
 	 * release their reference.
 	 */
 	while (p->p_lock > 0)
 		msleep(&p->p_lock, &p->p_mtx, PWAIT, "exithold", 0);
 
 	PROC_UNLOCK(p);
 	/* Drain the limit callout while we don't have the proc locked */
 	callout_drain(&p->p_limco);
 
 #ifdef AUDIT
 	/*
 	 * The Sun BSM exit token contains two components: an exit status as
 	 * passed to exit(), and a return value to indicate what sort of exit
 	 * it was.  The exit status is WEXITSTATUS(rv), but it's not clear
 	 * what the return value is.
 	 */
 	AUDIT_ARG_EXIT(rval, 0);
 	AUDIT_SYSCALL_EXIT(0, td);
 #endif
 
 	/* Are we a task leader with peers? */
 	if (p->p_peers != NULL && p == p->p_leader) {
 		mtx_lock(&ppeers_lock);
 		q = p->p_peers;
 		while (q != NULL) {
 			PROC_LOCK(q);
 			kern_psignal(q, SIGKILL);
 			PROC_UNLOCK(q);
 			q = q->p_peers;
 		}
 		while (p->p_peers != NULL)
 			msleep(p, &ppeers_lock, PWAIT, "exit1", 0);
 		mtx_unlock(&ppeers_lock);
 	}
 
 	/*
 	 * Check if any loadable modules need anything done at process exit.
 	 * E.g. SYSV IPC stuff.
 	 * Event handler could change exit status.
 	 * XXX what if one of these generates an error?
 	 */
 	EVENTHANDLER_DIRECT_INVOKE(process_exit, p);
 
 	/*
 	 * If parent is waiting for us to exit or exec,
 	 * P_PPWAIT is set; we will wakeup the parent below.
 	 */
 	PROC_LOCK(p);
 	stopprofclock(p);
 	p->p_flag &= ~(P_TRACED | P_PPWAIT | P_PPTRACE);
 	p->p_ptevents = 0;
 
 	/*
 	 * Stop the real interval timer.  If the handler is currently
 	 * executing, prevent it from rearming itself and let it finish.
 	 */
 	if (timevalisset(&p->p_realtimer.it_value) &&
 	    _callout_stop_safe(&p->p_itcallout, CS_EXECUTING, NULL) == 0) {
 		timevalclear(&p->p_realtimer.it_interval);
 		msleep(&p->p_itcallout, &p->p_mtx, PWAIT, "ritwait", 0);
 		KASSERT(!timevalisset(&p->p_realtimer.it_value),
 		    ("realtime timer is still armed"));
 	}
 
 	PROC_UNLOCK(p);
 
 	umtx_thread_exit(td);
 
 	/*
 	 * Reset any sigio structures pointing to us as a result of
 	 * F_SETOWN with our pid.
 	 */
 	funsetownlst(&p->p_sigiolst);
 
 	/*
 	 * If this process has an nlminfo data area (for lockd), release it
 	 */
 	if (nlminfo_release_p != NULL && p->p_nlminfo != NULL)
 		(*nlminfo_release_p)(p);
 
 	/*
 	 * Close open files and release open-file table.
 	 * This may block!
 	 */
 	fdescfree(td);
 
 	/*
 	 * If this thread tickled GEOM, we need to wait for the giggling to
 	 * stop before we return to userland
 	 */
 	if (td->td_pflags & TDP_GEOM)
 		g_waitidle();
 
 	/*
 	 * Remove ourself from our leader's peer list and wake our leader.
 	 */
 	if (p->p_leader->p_peers != NULL) {
 		mtx_lock(&ppeers_lock);
 		if (p->p_leader->p_peers != NULL) {
 			q = p->p_leader;
 			while (q->p_peers != p)
 				q = q->p_peers;
 			q->p_peers = p->p_peers;
 			wakeup(p->p_leader);
 		}
 		mtx_unlock(&ppeers_lock);
 	}
 
 	vmspace_exit(td);
 	killjobc();
 	(void)acct_process(td);
 
 #ifdef KTRACE
 	ktrprocexit(td);
 #endif
 	/*
 	 * Release reference to text vnode
 	 */
 	if (p->p_textvp != NULL) {
 		vrele(p->p_textvp);
 		p->p_textvp = NULL;
 	}
 
 	/*
 	 * Release our limits structure.
 	 */
 	lim_free(p->p_limit);
 	p->p_limit = NULL;
 
 	tidhash_remove(td);
 
 	/*
 	 * Remove proc from allproc queue and pidhash chain.
 	 * Place onto zombproc.  Unlink from parent's child list.
 	 */
 	sx_xlock(&allproc_lock);
 	LIST_REMOVE(p, p_list);
 	LIST_INSERT_HEAD(&zombproc, p, p_list);
 	LIST_REMOVE(p, p_hash);
 	sx_xunlock(&allproc_lock);
 
 	/*
 	 * Call machine-dependent code to release any
 	 * machine-dependent resources other than the address space.
 	 * The address space is released by "vmspace_exitfree(p)" in
 	 * vm_waitproc().
 	 */
 	cpu_exit(td);
 
 	WITNESS_WARN(WARN_PANIC, NULL, "process (pid %d) exiting", p->p_pid);
 
 	/*
 	 * Reparent all children processes:
 	 * - traced ones to the original parent (or init if we are that parent)
 	 * - the rest to init
 	 */
 	sx_xlock(&proctree_lock);
 	q = LIST_FIRST(&p->p_children);
 	if (q != NULL)		/* only need this if any child is S_ZOMB */
 		wakeup(q->p_reaper);
 	for (; q != NULL; q = nq) {
 		nq = LIST_NEXT(q, p_sibling);
 		ksi = ksiginfo_alloc(TRUE);
 		PROC_LOCK(q);
 		q->p_sigparent = SIGCHLD;
 
 		if (!(q->p_flag & P_TRACED)) {
 			proc_reparent(q, q->p_reaper);
 			if (q->p_state == PRS_ZOMBIE) {
 				/*
 				 * Inform reaper about the reparented
 				 * zombie, since wait(2) has something
 				 * new to report.  Guarantee queueing
 				 * of the SIGCHLD signal, similar to
 				 * the _exit() behaviour, by providing
 				 * our ksiginfo.  Ksi is freed by the
 				 * signal delivery.
 				 */
 				if (q->p_ksi == NULL) {
 					ksi1 = NULL;
 				} else {
 					ksiginfo_copy(q->p_ksi, ksi);
 					ksi->ksi_flags |= KSI_INS;
 					ksi1 = ksi;
 					ksi = NULL;
 				}
 				PROC_LOCK(q->p_reaper);
 				pksignal(q->p_reaper, SIGCHLD, ksi1);
 				PROC_UNLOCK(q->p_reaper);
 			} else if (q->p_pdeathsig > 0) {
 				/*
 				 * The child asked to received a signal
 				 * when we exit.
 				 */
 				kern_psignal(q, q->p_pdeathsig);
 			}
 		} else {
 			/*
 			 * Traced processes are killed since their existence
 			 * means someone is screwing up.
 			 */
 			t = proc_realparent(q);
 			if (t == p) {
 				proc_reparent(q, q->p_reaper);
 			} else {
 				PROC_LOCK(t);
 				proc_reparent(q, t);
 				PROC_UNLOCK(t);
 			}
 			/*
 			 * Since q was found on our children list, the
 			 * proc_reparent() call moved q to the orphan
 			 * list due to present P_TRACED flag. Clear
 			 * orphan link for q now while q is locked.
 			 */
 			clear_orphan(q);
 			q->p_flag &= ~(P_TRACED | P_STOPPED_TRACE);
 			q->p_flag2 &= ~P2_PTRACE_FSTP;
 			q->p_ptevents = 0;
 			FOREACH_THREAD_IN_PROC(q, tdt) {
 				tdt->td_dbgflags &= ~(TDB_SUSPEND | TDB_XSIG |
 				    TDB_FSTP);
 			}
 			kern_psignal(q, SIGKILL);
 		}
 		PROC_UNLOCK(q);
 		if (ksi != NULL)
 			ksiginfo_free(ksi);
 	}
 
 	/*
 	 * Also get rid of our orphans.
 	 */
 	while ((q = LIST_FIRST(&p->p_orphans)) != NULL) {
 		PROC_LOCK(q);
+		KASSERT(q->p_oppid == p->p_pid,
+		    ("orphan %p of %p has unexpected oppid %d", q, p,
+		    q->p_oppid));
+		q->p_oppid = q->p_reaper->p_pid;
+
 		/*
 		 * If we are the real parent of this process
 		 * but it has been reparented to a debugger, then
 		 * check if it asked for a signal when we exit.
 		 */
 		if (q->p_pdeathsig > 0)
 			kern_psignal(q, q->p_pdeathsig);
 		CTR2(KTR_PTRACE, "exit: pid %d, clearing orphan %d", p->p_pid,
 		    q->p_pid);
 		clear_orphan(q);
 		PROC_UNLOCK(q);
 	}
 
 	/* Save exit status. */
 	PROC_LOCK(p);
 	p->p_xthread = td;
 
 	/* Tell the prison that we are gone. */
 	prison_proc_free(p->p_ucred->cr_prison);
 
 #ifdef KDTRACE_HOOKS
 	/*
 	 * Tell the DTrace fasttrap provider about the exit if it
 	 * has declared an interest.
 	 */
 	if (dtrace_fasttrap_exit)
 		dtrace_fasttrap_exit(p);
 #endif
 
 	/*
 	 * Notify interested parties of our demise.
 	 */
 	KNOTE_LOCKED(p->p_klist, NOTE_EXIT);
 
 #ifdef KDTRACE_HOOKS
 	int reason = CLD_EXITED;
 	if (WCOREDUMP(signo))
 		reason = CLD_DUMPED;
 	else if (WIFSIGNALED(signo))
 		reason = CLD_KILLED;
 	SDT_PROBE1(proc, , , exit, reason);
 #endif
 
 	/*
 	 * If this is a process with a descriptor, we may not need to deliver
 	 * a signal to the parent.  proctree_lock is held over
 	 * procdesc_exit() to serialize concurrent calls to close() and
 	 * exit().
 	 */
 	if (p->p_procdesc == NULL || procdesc_exit(p)) {
 		/*
 		 * Notify parent that we're gone.  If parent has the
 		 * PS_NOCLDWAIT flag set, or if the handler is set to SIG_IGN,
 		 * notify process 1 instead (and hope it will handle this
 		 * situation).
 		 */
 		PROC_LOCK(p->p_pptr);
 		mtx_lock(&p->p_pptr->p_sigacts->ps_mtx);
 		if (p->p_pptr->p_sigacts->ps_flag &
 		    (PS_NOCLDWAIT | PS_CLDSIGIGN)) {
 			struct proc *pp;
 
 			mtx_unlock(&p->p_pptr->p_sigacts->ps_mtx);
 			pp = p->p_pptr;
 			PROC_UNLOCK(pp);
 			proc_reparent(p, p->p_reaper);
 			p->p_sigparent = SIGCHLD;
 			PROC_LOCK(p->p_pptr);
 
 			/*
 			 * Notify parent, so in case he was wait(2)ing or
 			 * executing waitpid(2) with our pid, he will
 			 * continue.
 			 */
 			wakeup(pp);
 		} else
 			mtx_unlock(&p->p_pptr->p_sigacts->ps_mtx);
 
 		if (p->p_pptr == p->p_reaper || p->p_pptr == initproc)
 			childproc_exited(p);
 		else if (p->p_sigparent != 0) {
 			if (p->p_sigparent == SIGCHLD)
 				childproc_exited(p);
 			else	/* LINUX thread */
 				kern_psignal(p->p_pptr, p->p_sigparent);
 		}
 	} else
 		PROC_LOCK(p->p_pptr);
 	sx_xunlock(&proctree_lock);
 
 	/*
 	 * The state PRS_ZOMBIE prevents other proesses from sending
 	 * signal to the process, to avoid memory leak, we free memory
 	 * for signal queue at the time when the state is set.
 	 */
 	sigqueue_flush(&p->p_sigqueue);
 	sigqueue_flush(&td->td_sigqueue);
 
 	/*
 	 * We have to wait until after acquiring all locks before
 	 * changing p_state.  We need to avoid all possible context
 	 * switches (including ones from blocking on a mutex) while
 	 * marked as a zombie.  We also have to set the zombie state
 	 * before we release the parent process' proc lock to avoid
 	 * a lost wakeup.  So, we first call wakeup, then we grab the
 	 * sched lock, update the state, and release the parent process'
 	 * proc lock.
 	 */
 	wakeup(p->p_pptr);
 	cv_broadcast(&p->p_pwait);
 	sched_exit(p->p_pptr, td);
 	PROC_SLOCK(p);
 	p->p_state = PRS_ZOMBIE;
 	PROC_UNLOCK(p->p_pptr);
 
 	/*
 	 * Save our children's rusage information in our exit rusage.
 	 */
 	PROC_STATLOCK(p);
 	ruadd(&p->p_ru, &p->p_rux, &p->p_stats->p_cru, &p->p_crux);
 	PROC_STATUNLOCK(p);
 
 	/*
 	 * Make sure the scheduler takes this thread out of its tables etc.
 	 * This will also release this thread's reference to the ucred.
 	 * Other thread parts to release include pcb bits and such.
 	 */
 	thread_exit();
 }
 
 
 #ifndef _SYS_SYSPROTO_H_
 struct abort2_args {
 	char *why;
 	int nargs;
 	void **args;
 };
 #endif
 
 int
 sys_abort2(struct thread *td, struct abort2_args *uap)
 {
 	struct proc *p = td->td_proc;
 	struct sbuf *sb;
 	void *uargs[16];
 	int error, i, sig;
 
 	/*
 	 * Do it right now so we can log either proper call of abort2(), or
 	 * note, that invalid argument was passed. 512 is big enough to
 	 * handle 16 arguments' descriptions with additional comments.
 	 */
 	sb = sbuf_new(NULL, NULL, 512, SBUF_FIXEDLEN);
 	sbuf_clear(sb);
 	sbuf_printf(sb, "%s(pid %d uid %d) aborted: ",
 	    p->p_comm, p->p_pid, td->td_ucred->cr_uid);
 	/*
 	 * Since we can't return from abort2(), send SIGKILL in cases, where
 	 * abort2() was called improperly
 	 */
 	sig = SIGKILL;
 	/* Prevent from DoSes from user-space. */
 	if (uap->nargs < 0 || uap->nargs > 16)
 		goto out;
 	if (uap->nargs > 0) {
 		if (uap->args == NULL)
 			goto out;
 		error = copyin(uap->args, uargs, uap->nargs * sizeof(void *));
 		if (error != 0)
 			goto out;
 	}
 	/*
 	 * Limit size of 'reason' string to 128. Will fit even when
 	 * maximal number of arguments was chosen to be logged.
 	 */
 	if (uap->why != NULL) {
 		error = sbuf_copyin(sb, uap->why, 128);
 		if (error < 0)
 			goto out;
 	} else {
 		sbuf_printf(sb, "(null)");
 	}
 	if (uap->nargs > 0) {
 		sbuf_printf(sb, "(");
 		for (i = 0;i < uap->nargs; i++)
 			sbuf_printf(sb, "%s%p", i == 0 ? "" : ", ", uargs[i]);
 		sbuf_printf(sb, ")");
 	}
 	/*
 	 * Final stage: arguments were proper, string has been
 	 * successfully copied from userspace, and copying pointers
 	 * from user-space succeed.
 	 */
 	sig = SIGABRT;
 out:
 	if (sig == SIGKILL) {
 		sbuf_trim(sb);
 		sbuf_printf(sb, " (Reason text inaccessible)");
 	}
 	sbuf_cat(sb, "\n");
 	sbuf_finish(sb);
 	log(LOG_INFO, "%s", sbuf_data(sb));
 	sbuf_delete(sb);
 	exit1(td, 0, sig);
 	return (0);
 }
 
 
 #ifdef COMPAT_43
 /*
  * The dirty work is handled by kern_wait().
  */
 int
 owait(struct thread *td, struct owait_args *uap __unused)
 {
 	int error, status;
 
 	error = kern_wait(td, WAIT_ANY, &status, 0, NULL);
 	if (error == 0)
 		td->td_retval[1] = status;
 	return (error);
 }
 #endif /* COMPAT_43 */
 
 /*
  * The dirty work is handled by kern_wait().
  */
 int
 sys_wait4(struct thread *td, struct wait4_args *uap)
 {
 	struct rusage ru, *rup;
 	int error, status;
 
 	if (uap->rusage != NULL)
 		rup = &ru;
 	else
 		rup = NULL;
 	error = kern_wait(td, uap->pid, &status, uap->options, rup);
 	if (uap->status != NULL && error == 0 && td->td_retval[0] != 0)
 		error = copyout(&status, uap->status, sizeof(status));
 	if (uap->rusage != NULL && error == 0 && td->td_retval[0] != 0)
 		error = copyout(&ru, uap->rusage, sizeof(struct rusage));
 	return (error);
 }
 
 int
 sys_wait6(struct thread *td, struct wait6_args *uap)
 {
 	struct __wrusage wru, *wrup;
 	siginfo_t si, *sip;
 	idtype_t idtype;
 	id_t id;
 	int error, status;
 
 	idtype = uap->idtype;
 	id = uap->id;
 
 	if (uap->wrusage != NULL)
 		wrup = &wru;
 	else
 		wrup = NULL;
 
 	if (uap->info != NULL) {
 		sip = &si;
 		bzero(sip, sizeof(*sip));
 	} else
 		sip = NULL;
 
 	/*
 	 *  We expect all callers of wait6() to know about WEXITED and
 	 *  WTRAPPED.
 	 */
 	error = kern_wait6(td, idtype, id, &status, uap->options, wrup, sip);
 
 	if (uap->status != NULL && error == 0 && td->td_retval[0] != 0)
 		error = copyout(&status, uap->status, sizeof(status));
 	if (uap->wrusage != NULL && error == 0 && td->td_retval[0] != 0)
 		error = copyout(&wru, uap->wrusage, sizeof(wru));
 	if (uap->info != NULL && error == 0)
 		error = copyout(&si, uap->info, sizeof(si));
 	return (error);
 }
 
 /*
  * Reap the remains of a zombie process and optionally return status and
  * rusage.  Asserts and will release both the proctree_lock and the process
  * lock as part of its work.
  */
 void
 proc_reap(struct thread *td, struct proc *p, int *status, int options)
 {
 	struct proc *q, *t;
 
 	sx_assert(&proctree_lock, SA_XLOCKED);
 	PROC_LOCK_ASSERT(p, MA_OWNED);
 	PROC_SLOCK_ASSERT(p, MA_OWNED);
 	KASSERT(p->p_state == PRS_ZOMBIE, ("proc_reap: !PRS_ZOMBIE"));
 
 	q = td->td_proc;
 
 	PROC_SUNLOCK(p);
 	if (status)
 		*status = KW_EXITCODE(p->p_xexit, p->p_xsig);
 	if (options & WNOWAIT) {
 		/*
 		 *  Only poll, returning the status.  Caller does not wish to
 		 * release the proc struct just yet.
 		 */
 		PROC_UNLOCK(p);
 		sx_xunlock(&proctree_lock);
 		return;
 	}
 
 	PROC_LOCK(q);
 	sigqueue_take(p->p_ksi);
 	PROC_UNLOCK(q);
 
 	/*
 	 * If we got the child via a ptrace 'attach', we need to give it back
 	 * to the old parent.
 	 */
 	if (p->p_oppid != 0 && p->p_oppid != p->p_pptr->p_pid) {
 		PROC_UNLOCK(p);
 		t = proc_realparent(p);
 		PROC_LOCK(t);
 		PROC_LOCK(p);
 		CTR2(KTR_PTRACE,
 		    "wait: traced child %d moved back to parent %d", p->p_pid,
 		    t->p_pid);
 		proc_reparent(p, t);
 		p->p_oppid = 0;
 		PROC_UNLOCK(p);
 		pksignal(t, SIGCHLD, p->p_ksi);
 		wakeup(t);
 		cv_broadcast(&p->p_pwait);
 		PROC_UNLOCK(t);
 		sx_xunlock(&proctree_lock);
 		return;
 	}
 	p->p_oppid = 0;
 	PROC_UNLOCK(p);
 
 	/*
 	 * Remove other references to this process to ensure we have an
 	 * exclusive reference.
 	 */
 	sx_xlock(&allproc_lock);
 	LIST_REMOVE(p, p_list);	/* off zombproc */
 	sx_xunlock(&allproc_lock);
 	LIST_REMOVE(p, p_sibling);
 	reaper_abandon_children(p, true);
 	LIST_REMOVE(p, p_reapsibling);
 	PROC_LOCK(p);
 	clear_orphan(p);
 	PROC_UNLOCK(p);
 	leavepgrp(p);
 	if (p->p_procdesc != NULL)
 		procdesc_reap(p);
 	sx_xunlock(&proctree_lock);
 
 	PROC_LOCK(p);
 	knlist_detach(p->p_klist);
 	p->p_klist = NULL;
 	PROC_UNLOCK(p);
 
 	/*
 	 * Removal from allproc list and process group list paired with
 	 * PROC_LOCK which was executed during that time should guarantee
 	 * nothing can reach this process anymore. As such further locking
 	 * is unnecessary.
 	 */
 	p->p_xexit = p->p_xsig = 0;		/* XXX: why? */
 
 	PROC_LOCK(q);
 	ruadd(&q->p_stats->p_cru, &q->p_crux, &p->p_ru, &p->p_rux);
 	PROC_UNLOCK(q);
 
 	/*
 	 * Decrement the count of procs running with this uid.
 	 */
 	(void)chgproccnt(p->p_ucred->cr_ruidinfo, -1, 0);
 
 	/*
 	 * Destroy resource accounting information associated with the process.
 	 */
 #ifdef RACCT
 	if (racct_enable) {
 		PROC_LOCK(p);
 		racct_sub(p, RACCT_NPROC, 1);
 		PROC_UNLOCK(p);
 	}
 #endif
 	racct_proc_exit(p);
 
 	/*
 	 * Free credentials, arguments, and sigacts.
 	 */
 	crfree(p->p_ucred);
 	proc_set_cred(p, NULL);
 	pargs_drop(p->p_args);
 	p->p_args = NULL;
 	sigacts_free(p->p_sigacts);
 	p->p_sigacts = NULL;
 
 	/*
 	 * Do any thread-system specific cleanups.
 	 */
 	thread_wait(p);
 
 	/*
 	 * Give vm and machine-dependent layer a chance to free anything that
 	 * cpu_exit couldn't release while still running in process context.
 	 */
 	vm_waitproc(p);
 #ifdef MAC
 	mac_proc_destroy(p);
 #endif
 	/*
 	 * Free any domain policy that's still hiding around.
 	 */
 	vm_domain_policy_cleanup(&p->p_vm_dom_policy);
 
 	KASSERT(FIRST_THREAD_IN_PROC(p),
 	    ("proc_reap: no residual thread!"));
 	uma_zfree(proc_zone, p);
 	atomic_add_int(&nprocs, -1);
 }
 
 static int
 proc_to_reap(struct thread *td, struct proc *p, idtype_t idtype, id_t id,
     int *status, int options, struct __wrusage *wrusage, siginfo_t *siginfo,
     int check_only)
 {
 	struct rusage *rup;
 
 	sx_assert(&proctree_lock, SA_XLOCKED);
 
 	PROC_LOCK(p);
 
 	switch (idtype) {
 	case P_ALL:
 		if (p->p_procdesc != NULL) {
 			PROC_UNLOCK(p);
 			return (0);
 		}
 		break;
 	case P_PID:
 		if (p->p_pid != (pid_t)id) {
 			PROC_UNLOCK(p);
 			return (0);
 		}
 		break;
 	case P_PGID:
 		if (p->p_pgid != (pid_t)id) {
 			PROC_UNLOCK(p);
 			return (0);
 		}
 		break;
 	case P_SID:
 		if (p->p_session->s_sid != (pid_t)id) {
 			PROC_UNLOCK(p);
 			return (0);
 		}
 		break;
 	case P_UID:
 		if (p->p_ucred->cr_uid != (uid_t)id) {
 			PROC_UNLOCK(p);
 			return (0);
 		}
 		break;
 	case P_GID:
 		if (p->p_ucred->cr_gid != (gid_t)id) {
 			PROC_UNLOCK(p);
 			return (0);
 		}
 		break;
 	case P_JAILID:
 		if (p->p_ucred->cr_prison->pr_id != (int)id) {
 			PROC_UNLOCK(p);
 			return (0);
 		}
 		break;
 	/*
 	 * It seems that the thread structures get zeroed out
 	 * at process exit.  This makes it impossible to
 	 * support P_SETID, P_CID or P_CPUID.
 	 */
 	default:
 		PROC_UNLOCK(p);
 		return (0);
 	}
 
 	if (p_canwait(td, p)) {
 		PROC_UNLOCK(p);
 		return (0);
 	}
 
 	if (((options & WEXITED) == 0) && (p->p_state == PRS_ZOMBIE)) {
 		PROC_UNLOCK(p);
 		return (0);
 	}
 
 	/*
 	 * This special case handles a kthread spawned by linux_clone
 	 * (see linux_misc.c).  The linux_wait4 and linux_waitpid
 	 * functions need to be able to distinguish between waiting
 	 * on a process and waiting on a thread.  It is a thread if
 	 * p_sigparent is not SIGCHLD, and the WLINUXCLONE option
 	 * signifies we want to wait for threads and not processes.
 	 */
 	if ((p->p_sigparent != SIGCHLD) ^
 	    ((options & WLINUXCLONE) != 0)) {
 		PROC_UNLOCK(p);
 		return (0);
 	}
 
 	if (siginfo != NULL) {
 		bzero(siginfo, sizeof(*siginfo));
 		siginfo->si_errno = 0;
 
 		/*
 		 * SUSv4 requires that the si_signo value is always
 		 * SIGCHLD. Obey it despite the rfork(2) interface
 		 * allows to request other signal for child exit
 		 * notification.
 		 */
 		siginfo->si_signo = SIGCHLD;
 
 		/*
 		 *  This is still a rough estimate.  We will fix the
 		 *  cases TRAPPED, STOPPED, and CONTINUED later.
 		 */
 		if (WCOREDUMP(p->p_xsig)) {
 			siginfo->si_code = CLD_DUMPED;
 			siginfo->si_status = WTERMSIG(p->p_xsig);
 		} else if (WIFSIGNALED(p->p_xsig)) {
 			siginfo->si_code = CLD_KILLED;
 			siginfo->si_status = WTERMSIG(p->p_xsig);
 		} else {
 			siginfo->si_code = CLD_EXITED;
 			siginfo->si_status = p->p_xexit;
 		}
 
 		siginfo->si_pid = p->p_pid;
 		siginfo->si_uid = p->p_ucred->cr_uid;
 
 		/*
 		 * The si_addr field would be useful additional
 		 * detail, but apparently the PC value may be lost
 		 * when we reach this point.  bzero() above sets
 		 * siginfo->si_addr to NULL.
 		 */
 	}
 
 	/*
 	 * There should be no reason to limit resources usage info to
 	 * exited processes only.  A snapshot about any resources used
 	 * by a stopped process may be exactly what is needed.
 	 */
 	if (wrusage != NULL) {
 		rup = &wrusage->wru_self;
 		*rup = p->p_ru;
 		PROC_STATLOCK(p);
 		calcru(p, &rup->ru_utime, &rup->ru_stime);
 		PROC_STATUNLOCK(p);
 
 		rup = &wrusage->wru_children;
 		*rup = p->p_stats->p_cru;
 		calccru(p, &rup->ru_utime, &rup->ru_stime);
 	}
 
 	if (p->p_state == PRS_ZOMBIE && !check_only) {
 		PROC_SLOCK(p);
 		proc_reap(td, p, status, options);
 		return (-1);
 	}
 	return (1);
 }
 
 int
 kern_wait(struct thread *td, pid_t pid, int *status, int options,
     struct rusage *rusage)
 {
 	struct __wrusage wru, *wrup;
 	idtype_t idtype;
 	id_t id;
 	int ret;
 
 	/*
 	 * Translate the special pid values into the (idtype, pid)
 	 * pair for kern_wait6.  The WAIT_MYPGRP case is handled by
 	 * kern_wait6() on its own.
 	 */
 	if (pid == WAIT_ANY) {
 		idtype = P_ALL;
 		id = 0;
 	} else if (pid < 0) {
 		idtype = P_PGID;
 		id = (id_t)-pid;
 	} else {
 		idtype = P_PID;
 		id = (id_t)pid;
 	}
 
 	if (rusage != NULL)
 		wrup = &wru;
 	else
 		wrup = NULL;
 
 	/*
 	 * For backward compatibility we implicitly add flags WEXITED
 	 * and WTRAPPED here.
 	 */
 	options |= WEXITED | WTRAPPED;
 	ret = kern_wait6(td, idtype, id, status, options, wrup, NULL);
 	if (rusage != NULL)
 		*rusage = wru.wru_self;
 	return (ret);
 }
 
 static void
 report_alive_proc(struct thread *td, struct proc *p, siginfo_t *siginfo,
     int *status, int options, int si_code)
 {
 	bool cont;
 
 	PROC_LOCK_ASSERT(p, MA_OWNED);
 	sx_assert(&proctree_lock, SA_XLOCKED);
 	MPASS(si_code == CLD_TRAPPED || si_code == CLD_STOPPED ||
 	    si_code == CLD_CONTINUED);
 
 	cont = si_code == CLD_CONTINUED;
 	if ((options & WNOWAIT) == 0) {
 		if (cont)
 			p->p_flag &= ~P_CONTINUED;
 		else
 			p->p_flag |= P_WAITED;
 		PROC_LOCK(td->td_proc);
 		sigqueue_take(p->p_ksi);
 		PROC_UNLOCK(td->td_proc);
 	}
 	sx_xunlock(&proctree_lock);
 	if (siginfo != NULL) {
 		siginfo->si_code = si_code;
 		siginfo->si_status = cont ? SIGCONT : p->p_xsig;
 	}
 	if (status != NULL)
 		*status = cont ? SIGCONT : W_STOPCODE(p->p_xsig);
 	PROC_UNLOCK(p);
 	td->td_retval[0] = p->p_pid;
 }
 
 int
 kern_wait6(struct thread *td, idtype_t idtype, id_t id, int *status,
     int options, struct __wrusage *wrusage, siginfo_t *siginfo)
 {
 	struct proc *p, *q;
 	pid_t pid;
 	int error, nfound, ret;
 
 	AUDIT_ARG_VALUE((int)idtype);	/* XXX - This is likely wrong! */
 	AUDIT_ARG_PID((pid_t)id);	/* XXX - This may be wrong! */
 	AUDIT_ARG_VALUE(options);
 
 	q = td->td_proc;
 
 	if ((pid_t)id == WAIT_MYPGRP && (idtype == P_PID || idtype == P_PGID)) {
 		PROC_LOCK(q);
 		id = (id_t)q->p_pgid;
 		PROC_UNLOCK(q);
 		idtype = P_PGID;
 	}
 
 	/* If we don't know the option, just return. */
 	if ((options & ~(WUNTRACED | WNOHANG | WCONTINUED | WNOWAIT |
 	    WEXITED | WTRAPPED | WLINUXCLONE)) != 0)
 		return (EINVAL);
 	if ((options & (WEXITED | WUNTRACED | WCONTINUED | WTRAPPED)) == 0) {
 		/*
 		 * We will be unable to find any matching processes,
 		 * because there are no known events to look for.
 		 * Prefer to return error instead of blocking
 		 * indefinitely.
 		 */
 		return (EINVAL);
 	}
 
 loop:
 	if (q->p_flag & P_STATCHILD) {
 		PROC_LOCK(q);
 		q->p_flag &= ~P_STATCHILD;
 		PROC_UNLOCK(q);
 	}
 	nfound = 0;
 	sx_xlock(&proctree_lock);
 	LIST_FOREACH(p, &q->p_children, p_sibling) {
 		pid = p->p_pid;
 		ret = proc_to_reap(td, p, idtype, id, status, options,
 		    wrusage, siginfo, 0);
 		if (ret == 0)
 			continue;
 		else if (ret == 1)
 			nfound++;
 		else {
 			td->td_retval[0] = pid;
 			return (0);
 		}
 
 		PROC_LOCK_ASSERT(p, MA_OWNED);
 
 		if ((options & (WTRAPPED | WUNTRACED)) != 0)
 			PROC_SLOCK(p);
 
 		if ((options & WTRAPPED) != 0 &&
 		    (p->p_flag & P_TRACED) != 0 &&
 		    (p->p_flag & (P_STOPPED_TRACE | P_STOPPED_SIG)) != 0 &&
 		    p->p_suspcount == p->p_numthreads &&
 		    (p->p_flag & P_WAITED) == 0) {
 			PROC_SUNLOCK(p);
 			CTR4(KTR_PTRACE,
 			    "wait: returning trapped pid %d status %#x "
 			    "(xstat %d) xthread %d",
 			    p->p_pid, W_STOPCODE(p->p_xsig), p->p_xsig,
 			    p->p_xthread != NULL ?
 			    p->p_xthread->td_tid : -1);
 			report_alive_proc(td, p, siginfo, status, options,
 			    CLD_TRAPPED);
 			return (0);
 			}
 		if ((options & WUNTRACED) != 0 &&
 		    (p->p_flag & P_STOPPED_SIG) != 0 &&
 		    p->p_suspcount == p->p_numthreads &&
 		    (p->p_flag & P_WAITED) == 0) {
 			PROC_SUNLOCK(p);
 			report_alive_proc(td, p, siginfo, status, options,
 			    CLD_STOPPED);
 			return (0);
 		}
 		if ((options & (WTRAPPED | WUNTRACED)) != 0)
 			PROC_SUNLOCK(p);
 		if ((options & WCONTINUED) != 0 &&
 		    (p->p_flag & P_CONTINUED) != 0) {
 			report_alive_proc(td, p, siginfo, status, options,
 			    CLD_CONTINUED);
 			return (0);
 		}
 		PROC_UNLOCK(p);
 	}
 
 	/*
 	 * Look in the orphans list too, to allow the parent to
 	 * collect it's child exit status even if child is being
 	 * debugged.
 	 *
 	 * Debugger detaches from the parent upon successful
 	 * switch-over from parent to child.  At this point due to
 	 * re-parenting the parent loses the child to debugger and a
 	 * wait4(2) call would report that it has no children to wait
 	 * for.  By maintaining a list of orphans we allow the parent
 	 * to successfully wait until the child becomes a zombie.
 	 */
 	if (nfound == 0) {
 		LIST_FOREACH(p, &q->p_orphans, p_orphan) {
 			ret = proc_to_reap(td, p, idtype, id, NULL, options,
 			    NULL, NULL, 1);
 			if (ret != 0) {
 				KASSERT(ret != -1, ("reaped an orphan (pid %d)",
 				    (int)td->td_retval[0]));
 				PROC_UNLOCK(p);
 				nfound++;
 				break;
 			}
 		}
 	}
 	if (nfound == 0) {
 		sx_xunlock(&proctree_lock);
 		return (ECHILD);
 	}
 	if (options & WNOHANG) {
 		sx_xunlock(&proctree_lock);
 		td->td_retval[0] = 0;
 		return (0);
 	}
 	PROC_LOCK(q);
 	sx_xunlock(&proctree_lock);
 	if (q->p_flag & P_STATCHILD) {
 		q->p_flag &= ~P_STATCHILD;
 		error = 0;
 	} else
 		error = msleep(q, &q->p_mtx, PWAIT | PCATCH, "wait", 0);
 	PROC_UNLOCK(q);
 	if (error)
 		return (error);
 	goto loop;
 }
 
 /*
  * Make process 'parent' the new parent of process 'child'.
  * Must be called with an exclusive hold of proctree lock.
  */
 void
 proc_reparent(struct proc *child, struct proc *parent)
 {
 
 	sx_assert(&proctree_lock, SX_XLOCKED);
 	PROC_LOCK_ASSERT(child, MA_OWNED);
 	if (child->p_pptr == parent)
 		return;
 
 	PROC_LOCK(child->p_pptr);
 	sigqueue_take(child->p_ksi);
 	PROC_UNLOCK(child->p_pptr);
 	LIST_REMOVE(child, p_sibling);
 	LIST_INSERT_HEAD(&parent->p_children, child, p_sibling);
 
 	clear_orphan(child);
 	if (child->p_flag & P_TRACED) {
 		if (LIST_EMPTY(&child->p_pptr->p_orphans)) {
 			child->p_treeflag |= P_TREE_FIRST_ORPHAN;
 			LIST_INSERT_HEAD(&child->p_pptr->p_orphans, child,
 			    p_orphan);
 		} else {
 			LIST_INSERT_AFTER(LIST_FIRST(&child->p_pptr->p_orphans),
 			    child, p_orphan);
 		}
 		child->p_treeflag |= P_TREE_ORPHANED;
 	}
 
 	child->p_pptr = parent;
 }
Index: stable/11/tests/sys/kern/ptrace_test.c
===================================================================
--- stable/11/tests/sys/kern/ptrace_test.c	(revision 346540)
+++ stable/11/tests/sys/kern/ptrace_test.c	(revision 346541)
@@ -1,3909 +1,3971 @@
 /*-
  * Copyright (c) 2015 John Baldwin <jhb@FreeBSD.org>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  *
  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
 
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
 #include <sys/types.h>
 #include <sys/cpuset.h>
 #include <sys/event.h>
 #include <sys/file.h>
 #include <sys/time.h>
 #include <sys/procctl.h>
 #include <sys/ptrace.h>
 #include <sys/queue.h>
 #include <sys/runq.h>
 #include <sys/syscall.h>
 #include <sys/sysctl.h>
 #include <sys/user.h>
 #include <sys/wait.h>
 #include <errno.h>
 #include <machine/cpufunc.h>
 #include <pthread.h>
 #include <sched.h>
 #include <semaphore.h>
 #include <signal.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <atf-c.h>
 
 /*
  * Architectures with a user-visible breakpoint().
  */
 #if defined(__aarch64__) || defined(__amd64__) || defined(__arm__) ||	\
     defined(__i386__) || defined(__mips__) || defined(__riscv) ||	\
     defined(__sparc64__)
 #define	HAVE_BREAKPOINT
 #endif
 
 /*
  * Adjust PC to skip over a breakpoint when stopped for a breakpoint trap.
  */
 #ifdef HAVE_BREAKPOINT
 #if defined(__aarch64__)
 #define	SKIP_BREAK(reg)	((reg)->elr += 4)
 #elif defined(__amd64__) || defined(__i386__)
 #define	SKIP_BREAK(reg)
 #elif defined(__arm__)
 #define	SKIP_BREAK(reg)	((reg)->r_pc += 4)
 #elif defined(__mips__)
 #define	SKIP_BREAK(reg)	((reg)->r_regs[PC] += 4)
 #elif defined(__riscv)
 #define	SKIP_BREAK(reg)	((reg)->sepc += 4)
 #elif defined(__sparc64__)
 #define	SKIP_BREAK(reg)	do {						\
 	(reg)->r_tpc = (reg)->r_tnpc + 4;				\
 	(reg)->r_tnpc += 8;						\
 } while (0)
 #endif
 #endif
 
 /*
  * A variant of ATF_REQUIRE that is suitable for use in child
  * processes.  This only works if the parent process is tripped up by
  * the early exit and fails some requirement itself.
  */
 #define	CHILD_REQUIRE(exp) do {						\
 		if (!(exp))						\
 			child_fail_require(__FILE__, __LINE__,		\
 			    #exp " not met");				\
 	} while (0)
 
 static __dead2 void
 child_fail_require(const char *file, int line, const char *str)
 {
 	char buf[128];
 
 	snprintf(buf, sizeof(buf), "%s:%d: %s\n", file, line, str);
 	write(2, buf, strlen(buf));
 	_exit(32);
 }
 
 static void
 trace_me(void)
 {
 
 	/* Attach the parent process as a tracer of this process. */
 	CHILD_REQUIRE(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
 
 	/* Trigger a stop. */
 	raise(SIGSTOP);
 }
 
 static void
 attach_child(pid_t pid)
 {
 	pid_t wpid;
 	int status;
 
 	ATF_REQUIRE(ptrace(PT_ATTACH, pid, NULL, 0) == 0);
 
 	wpid = waitpid(pid, &status, 0);
 	ATF_REQUIRE(wpid == pid);
 	ATF_REQUIRE(WIFSTOPPED(status));
 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
 }
 
 static void
 wait_for_zombie(pid_t pid)
 {
 
 	/*
 	 * Wait for a process to exit.  This is kind of gross, but
 	 * there is not a better way.
 	 *
 	 * Prior to r325719, the kern.proc.pid.<pid> sysctl failed
 	 * with ESRCH.  After that change, a valid struct kinfo_proc
 	 * is returned for zombies with ki_stat set to SZOMB.
 	 */
 	for (;;) {
 		struct kinfo_proc kp;
 		size_t len;
 		int mib[4];
 
 		mib[0] = CTL_KERN;
 		mib[1] = KERN_PROC;
 		mib[2] = KERN_PROC_PID;
 		mib[3] = pid;
 		len = sizeof(kp);
 		if (sysctl(mib, nitems(mib), &kp, &len, NULL, 0) == -1) {
 			ATF_REQUIRE(errno == ESRCH);
 			break;
 		}
 		if (kp.ki_stat == SZOMB)
 			break;
 		usleep(5000);
 	}
 }
 
 /*
  * Verify that a parent debugger process "sees" the exit of a debugged
  * process exactly once when attached via PT_TRACE_ME.
  */
 ATF_TC_WITHOUT_HEAD(ptrace__parent_wait_after_trace_me);
 ATF_TC_BODY(ptrace__parent_wait_after_trace_me, tc)
 {
 	pid_t child, wpid;
 	int status;
 
 	ATF_REQUIRE((child = fork()) != -1);
 	if (child == 0) {
 		/* Child process. */
 		trace_me();
 
 		_exit(1);
 	}
 
 	/* Parent process. */
 
 	/* The first wait() should report the stop from SIGSTOP. */
 	wpid = waitpid(child, &status, 0);
 	ATF_REQUIRE(wpid == child);
 	ATF_REQUIRE(WIFSTOPPED(status));
 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
 
 	/* Continue the child ignoring the SIGSTOP. */
 	ATF_REQUIRE(ptrace(PT_CONTINUE, child, (caddr_t)1, 0) != -1);
 
 	/* The second wait() should report the exit status. */
 	wpid = waitpid(child, &status, 0);
 	ATF_REQUIRE(wpid == child);
 	ATF_REQUIRE(WIFEXITED(status));
 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
 
 	/* The child should no longer exist. */
 	wpid = waitpid(child, &status, 0);
 	ATF_REQUIRE(wpid == -1);
 	ATF_REQUIRE(errno == ECHILD);
 }
 
 /*
  * Verify that a parent debugger process "sees" the exit of a debugged
  * process exactly once when attached via PT_ATTACH.
  */
 ATF_TC_WITHOUT_HEAD(ptrace__parent_wait_after_attach);
 ATF_TC_BODY(ptrace__parent_wait_after_attach, tc)
 {
 	pid_t child, wpid;
 	int cpipe[2], status;
 	char c;
 
 	ATF_REQUIRE(pipe(cpipe) == 0);
 	ATF_REQUIRE((child = fork()) != -1);
 	if (child == 0) {
 		/* Child process. */
 		close(cpipe[0]);
 
 		/* Wait for the parent to attach. */
 		CHILD_REQUIRE(read(cpipe[1], &c, sizeof(c)) == 0);
 
 		_exit(1);
 	}
 	close(cpipe[1]);
 
 	/* Parent process. */
 
 	/* Attach to the child process. */
 	attach_child(child);
 
 	/* Continue the child ignoring the SIGSTOP. */
 	ATF_REQUIRE(ptrace(PT_CONTINUE, child, (caddr_t)1, 0) != -1);
 
 	/* Signal the child to exit. */
 	close(cpipe[0]);
 
 	/* The second wait() should report the exit status. */
 	wpid = waitpid(child, &status, 0);
 	ATF_REQUIRE(wpid == child);
 	ATF_REQUIRE(WIFEXITED(status));
 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
 
 	/* The child should no longer exist. */
 	wpid = waitpid(child, &status, 0);
 	ATF_REQUIRE(wpid == -1);
 	ATF_REQUIRE(errno == ECHILD);
 }
 
 /*
  * Verify that a parent process "sees" the exit of a debugged process only
  * after the debugger has seen it.
  */
 ATF_TC_WITHOUT_HEAD(ptrace__parent_sees_exit_after_child_debugger);
 ATF_TC_BODY(ptrace__parent_sees_exit_after_child_debugger, tc)
 {
 	pid_t child, debugger, wpid;
 	int cpipe[2], dpipe[2], status;
 	char c;
 
 	ATF_REQUIRE(pipe(cpipe) == 0);
 	ATF_REQUIRE((child = fork()) != -1);
 
 	if (child == 0) {
 		/* Child process. */
 		close(cpipe[0]);
 
 		/* Wait for parent to be ready. */
 		CHILD_REQUIRE(read(cpipe[1], &c, sizeof(c)) == sizeof(c));
 
 		_exit(1);
 	}
 	close(cpipe[1]);
 
 	ATF_REQUIRE(pipe(dpipe) == 0);
 	ATF_REQUIRE((debugger = fork()) != -1);
 
 	if (debugger == 0) {
 		/* Debugger process. */
 		close(dpipe[0]);
 
 		CHILD_REQUIRE(ptrace(PT_ATTACH, child, NULL, 0) != -1);
 
 		wpid = waitpid(child, &status, 0);
 		CHILD_REQUIRE(wpid == child);
 		CHILD_REQUIRE(WIFSTOPPED(status));
 		CHILD_REQUIRE(WSTOPSIG(status) == SIGSTOP);
 
 		CHILD_REQUIRE(ptrace(PT_CONTINUE, child, (caddr_t)1, 0) != -1);
 
 		/* Signal parent that debugger is attached. */
 		CHILD_REQUIRE(write(dpipe[1], &c, sizeof(c)) == sizeof(c));
 
 		/* Wait for parent's failed wait. */
 		CHILD_REQUIRE(read(dpipe[1], &c, sizeof(c)) == 0);
 
 		wpid = waitpid(child, &status, 0);
 		CHILD_REQUIRE(wpid == child);
 		CHILD_REQUIRE(WIFEXITED(status));
 		CHILD_REQUIRE(WEXITSTATUS(status) == 1);
 
 		_exit(0);
 	}
 	close(dpipe[1]);
 
 	/* Parent process. */
 
 	/* Wait for the debugger to attach to the child. */
 	ATF_REQUIRE(read(dpipe[0], &c, sizeof(c)) == sizeof(c));
 
 	/* Release the child. */
 	ATF_REQUIRE(write(cpipe[0], &c, sizeof(c)) == sizeof(c));
 	ATF_REQUIRE(read(cpipe[0], &c, sizeof(c)) == 0);
 	close(cpipe[0]);
 
 	wait_for_zombie(child);
 
 	/*
 	 * This wait should return a pid of 0 to indicate no status to
 	 * report.  The parent should see the child as non-exited
 	 * until the debugger sees the exit.
 	 */
 	wpid = waitpid(child, &status, WNOHANG);
 	ATF_REQUIRE(wpid == 0);
 
 	/* Signal the debugger to wait for the child. */
 	close(dpipe[0]);
 
 	/* Wait for the debugger. */
 	wpid = waitpid(debugger, &status, 0);
 	ATF_REQUIRE(wpid == debugger);
 	ATF_REQUIRE(WIFEXITED(status));
 	ATF_REQUIRE(WEXITSTATUS(status) == 0);
 
 	/* The child process should now be ready. */
 	wpid = waitpid(child, &status, WNOHANG);
 	ATF_REQUIRE(wpid == child);
 	ATF_REQUIRE(WIFEXITED(status));
 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
 }
 
 /*
  * Verify that a parent process "sees" the exit of a debugged process
  * only after a non-direct-child debugger has seen it.  In particular,
  * various wait() calls in the parent must avoid failing with ESRCH by
  * checking the parent's orphan list for the debugee.
  */
 ATF_TC_WITHOUT_HEAD(ptrace__parent_sees_exit_after_unrelated_debugger);
 ATF_TC_BODY(ptrace__parent_sees_exit_after_unrelated_debugger, tc)
 {
 	pid_t child, debugger, fpid, wpid;
 	int cpipe[2], dpipe[2], status;
 	char c;
 
 	ATF_REQUIRE(pipe(cpipe) == 0);
 	ATF_REQUIRE((child = fork()) != -1);
 
 	if (child == 0) {
 		/* Child process. */
 		close(cpipe[0]);
 
 		/* Wait for parent to be ready. */
 		CHILD_REQUIRE(read(cpipe[1], &c, sizeof(c)) == sizeof(c));
 
 		_exit(1);
 	}
 	close(cpipe[1]);
 
 	ATF_REQUIRE(pipe(dpipe) == 0);
 	ATF_REQUIRE((debugger = fork()) != -1);
 
 	if (debugger == 0) {
 		/* Debugger parent. */
 
 		/*
 		 * Fork again and drop the debugger parent so that the
 		 * debugger is not a child of the main parent.
 		 */
 		CHILD_REQUIRE((fpid = fork()) != -1);
 		if (fpid != 0)
 			_exit(2);
 
 		/* Debugger process. */
 		close(dpipe[0]);
 
 		CHILD_REQUIRE(ptrace(PT_ATTACH, child, NULL, 0) != -1);
 
 		wpid = waitpid(child, &status, 0);
 		CHILD_REQUIRE(wpid == child);
 		CHILD_REQUIRE(WIFSTOPPED(status));
 		CHILD_REQUIRE(WSTOPSIG(status) == SIGSTOP);
 
 		CHILD_REQUIRE(ptrace(PT_CONTINUE, child, (caddr_t)1, 0) != -1);
 
 		/* Signal parent that debugger is attached. */
 		CHILD_REQUIRE(write(dpipe[1], &c, sizeof(c)) == sizeof(c));
 
 		/* Wait for parent's failed wait. */
 		CHILD_REQUIRE(read(dpipe[1], &c, sizeof(c)) == sizeof(c));
 
 		wpid = waitpid(child, &status, 0);
 		CHILD_REQUIRE(wpid == child);
 		CHILD_REQUIRE(WIFEXITED(status));
 		CHILD_REQUIRE(WEXITSTATUS(status) == 1);
 
 		_exit(0);
 	}
 	close(dpipe[1]);
 
 	/* Parent process. */
 
 	/* Wait for the debugger parent process to exit. */
 	wpid = waitpid(debugger, &status, 0);
 	ATF_REQUIRE(wpid == debugger);
 	ATF_REQUIRE(WIFEXITED(status));
 	ATF_REQUIRE(WEXITSTATUS(status) == 2);
 
 	/* A WNOHANG wait here should see the non-exited child. */
 	wpid = waitpid(child, &status, WNOHANG);
 	ATF_REQUIRE(wpid == 0);
 
 	/* Wait for the debugger to attach to the child. */
 	ATF_REQUIRE(read(dpipe[0], &c, sizeof(c)) == sizeof(c));
 
 	/* Release the child. */
 	ATF_REQUIRE(write(cpipe[0], &c, sizeof(c)) == sizeof(c));
 	ATF_REQUIRE(read(cpipe[0], &c, sizeof(c)) == 0);
 	close(cpipe[0]);
 
 	wait_for_zombie(child);
 
 	/*
 	 * This wait should return a pid of 0 to indicate no status to
 	 * report.  The parent should see the child as non-exited
 	 * until the debugger sees the exit.
 	 */
 	wpid = waitpid(child, &status, WNOHANG);
 	ATF_REQUIRE(wpid == 0);
 
 	/* Signal the debugger to wait for the child. */
 	ATF_REQUIRE(write(dpipe[0], &c, sizeof(c)) == sizeof(c));
 
 	/* Wait for the debugger. */
 	ATF_REQUIRE(read(dpipe[0], &c, sizeof(c)) == 0);
 	close(dpipe[0]);
 
 	/* The child process should now be ready. */
 	wpid = waitpid(child, &status, WNOHANG);
 	ATF_REQUIRE(wpid == child);
 	ATF_REQUIRE(WIFEXITED(status));
 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
 }
 
 /*
+ * Make sure that we can collect the exit status of an orphaned process.
+ */
+ATF_TC_WITHOUT_HEAD(ptrace__parent_exits_before_child);
+ATF_TC_BODY(ptrace__parent_exits_before_child, tc)
+{
+	ssize_t n;
+	int cpipe1[2], cpipe2[2], gcpipe[2], status;
+	pid_t child, gchild;
+
+	ATF_REQUIRE(pipe(cpipe1) == 0);
+	ATF_REQUIRE(pipe(cpipe2) == 0);
+	ATF_REQUIRE(pipe(gcpipe) == 0);
+
+	ATF_REQUIRE(procctl(P_PID, getpid(), PROC_REAP_ACQUIRE, NULL) == 0);
+
+	ATF_REQUIRE((child = fork()) != -1);
+	if (child == 0) {
+		CHILD_REQUIRE((gchild = fork()) != -1);
+		if (gchild == 0) {
+			status = 1;
+			do {
+				n = read(gcpipe[0], &status, sizeof(status));
+			} while (n == -1 && errno == EINTR);
+			_exit(status);
+		}
+
+		CHILD_REQUIRE(write(cpipe1[1], &gchild, sizeof(gchild)) ==
+		    sizeof(gchild));
+		CHILD_REQUIRE(read(cpipe2[0], &status, sizeof(status)) ==
+		    sizeof(status));
+		_exit(status);
+	}
+
+	ATF_REQUIRE(read(cpipe1[0], &gchild, sizeof(gchild)) == sizeof(gchild));
+
+	ATF_REQUIRE(ptrace(PT_ATTACH, gchild, NULL, 0) == 0);
+
+	status = 0;
+	ATF_REQUIRE(write(cpipe2[1], &status, sizeof(status)) ==
+	    sizeof(status));
+	ATF_REQUIRE(waitpid(child, &status, 0) == child);
+	ATF_REQUIRE(WIFEXITED(status) && WEXITSTATUS(status) == 0);
+
+	status = 0;
+	ATF_REQUIRE(write(gcpipe[1], &status, sizeof(status)) ==
+	    sizeof(status));
+	ATF_REQUIRE(waitpid(gchild, &status, 0) == gchild);
+	ATF_REQUIRE(WIFSTOPPED(status));
+	ATF_REQUIRE(ptrace(PT_DETACH, gchild, (caddr_t)1, 0) == 0);
+	ATF_REQUIRE(waitpid(gchild, &status, 0) == gchild);
+	ATF_REQUIRE(WIFEXITED(status) && WEXITSTATUS(status) == 0);
+
+	ATF_REQUIRE(close(cpipe1[0]) == 0);
+	ATF_REQUIRE(close(cpipe1[1]) == 0);
+	ATF_REQUIRE(close(cpipe2[0]) == 0);
+	ATF_REQUIRE(close(cpipe2[1]) == 0);
+	ATF_REQUIRE(close(gcpipe[0]) == 0);
+	ATF_REQUIRE(close(gcpipe[1]) == 0);
+}
+
+/*
  * The parent process should always act the same regardless of how the
  * debugger is attached to it.
  */
 static __dead2 void
 follow_fork_parent(bool use_vfork)
 {
 	pid_t fpid, wpid;
 	int status;
 
 	if (use_vfork)
 		CHILD_REQUIRE((fpid = vfork()) != -1);
 	else
 		CHILD_REQUIRE((fpid = fork()) != -1);
 
 	if (fpid == 0)
 		/* Child */
 		_exit(2);
 
 	wpid = waitpid(fpid, &status, 0);
 	CHILD_REQUIRE(wpid == fpid);
 	CHILD_REQUIRE(WIFEXITED(status));
 	CHILD_REQUIRE(WEXITSTATUS(status) == 2);
 
 	_exit(1);
 }
 
 /*
  * Helper routine for follow fork tests.  This waits for two stops
  * that report both "sides" of a fork.  It returns the pid of the new
  * child process.
  */
 static pid_t
 handle_fork_events(pid_t parent, struct ptrace_lwpinfo *ppl)
 {
 	struct ptrace_lwpinfo pl;
 	bool fork_reported[2];
 	pid_t child, wpid;
 	int i, status;
 
 	fork_reported[0] = false;
 	fork_reported[1] = false;
 	child = -1;
 	
 	/*
 	 * Each process should report a fork event.  The parent should
 	 * report a PL_FLAG_FORKED event, and the child should report
 	 * a PL_FLAG_CHILD event.
 	 */
 	for (i = 0; i < 2; i++) {
 		wpid = wait(&status);
 		ATF_REQUIRE(wpid > 0);
 		ATF_REQUIRE(WIFSTOPPED(status));
 
 		ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
 		    sizeof(pl)) != -1);
 		ATF_REQUIRE((pl.pl_flags & (PL_FLAG_FORKED | PL_FLAG_CHILD)) !=
 		    0);
 		ATF_REQUIRE((pl.pl_flags & (PL_FLAG_FORKED | PL_FLAG_CHILD)) !=
 		    (PL_FLAG_FORKED | PL_FLAG_CHILD));
 		if (pl.pl_flags & PL_FLAG_CHILD) {
 			ATF_REQUIRE(wpid != parent);
 			ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
 			ATF_REQUIRE(!fork_reported[1]);
 			if (child == -1)
 				child = wpid;
 			else
 				ATF_REQUIRE(child == wpid);
 			if (ppl != NULL)
 				ppl[1] = pl;
 			fork_reported[1] = true;
 		} else {
 			ATF_REQUIRE(wpid == parent);
 			ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
 			ATF_REQUIRE(!fork_reported[0]);
 			if (child == -1)
 				child = pl.pl_child_pid;
 			else
 				ATF_REQUIRE(child == pl.pl_child_pid);
 			if (ppl != NULL)
 				ppl[0] = pl;
 			fork_reported[0] = true;
 		}
 	}
 
 	return (child);
 }
 
 /*
  * Verify that a new child process is stopped after a followed fork and
  * that the traced parent sees the exit of the child after the debugger
  * when both processes remain attached to the debugger.
  */
 ATF_TC_WITHOUT_HEAD(ptrace__follow_fork_both_attached);
 ATF_TC_BODY(ptrace__follow_fork_both_attached, tc)
 {
 	pid_t children[2], fpid, wpid;
 	int status;
 
 	ATF_REQUIRE((fpid = fork()) != -1);
 	if (fpid == 0) {
 		trace_me();
 		follow_fork_parent(false);
 	}
 
 	/* Parent process. */
 	children[0] = fpid;
 
 	/* The first wait() should report the stop from SIGSTOP. */
 	wpid = waitpid(children[0], &status, 0);
 	ATF_REQUIRE(wpid == children[0]);
 	ATF_REQUIRE(WIFSTOPPED(status));
 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
 
 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1);
 
 	/* Continue the child ignoring the SIGSTOP. */
 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
 
 	children[1] = handle_fork_events(children[0], NULL);
 	ATF_REQUIRE(children[1] > 0);
 
 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[1], (caddr_t)1, 0) != -1);
 
 	/*
 	 * The child can't exit until the grandchild reports status, so the
 	 * grandchild should report its exit first to the debugger.
 	 */
 	wpid = wait(&status);
 	ATF_REQUIRE(wpid == children[1]);
 	ATF_REQUIRE(WIFEXITED(status));
 	ATF_REQUIRE(WEXITSTATUS(status) == 2);
 
 	wpid = wait(&status);
 	ATF_REQUIRE(wpid == children[0]);
 	ATF_REQUIRE(WIFEXITED(status));
 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
 
 	wpid = wait(&status);
 	ATF_REQUIRE(wpid == -1);
 	ATF_REQUIRE(errno == ECHILD);
 }
 
 /*
  * Verify that a new child process is stopped after a followed fork
  * and that the traced parent sees the exit of the child when the new
  * child process is detached after it reports its fork.
  */
 ATF_TC_WITHOUT_HEAD(ptrace__follow_fork_child_detached);
 ATF_TC_BODY(ptrace__follow_fork_child_detached, tc)
 {
 	pid_t children[2], fpid, wpid;
 	int status;
 
 	ATF_REQUIRE((fpid = fork()) != -1);
 	if (fpid == 0) {
 		trace_me();
 		follow_fork_parent(false);
 	}
 
 	/* Parent process. */
 	children[0] = fpid;
 
 	/* The first wait() should report the stop from SIGSTOP. */
 	wpid = waitpid(children[0], &status, 0);
 	ATF_REQUIRE(wpid == children[0]);
 	ATF_REQUIRE(WIFSTOPPED(status));
 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
 
 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1);
 
 	/* Continue the child ignoring the SIGSTOP. */
 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
 
 	children[1] = handle_fork_events(children[0], NULL);
 	ATF_REQUIRE(children[1] > 0);
 
 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
 	ATF_REQUIRE(ptrace(PT_DETACH, children[1], (caddr_t)1, 0) != -1);
 
 	/*
 	 * Should not see any status from the grandchild now, only the
 	 * child.
 	 */
 	wpid = wait(&status);
 	ATF_REQUIRE(wpid == children[0]);
 	ATF_REQUIRE(WIFEXITED(status));
 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
 
 	wpid = wait(&status);
 	ATF_REQUIRE(wpid == -1);
 	ATF_REQUIRE(errno == ECHILD);
 }
 
 /*
  * Verify that a new child process is stopped after a followed fork
  * and that the traced parent sees the exit of the child when the
  * traced parent is detached after the fork.
  */
 ATF_TC_WITHOUT_HEAD(ptrace__follow_fork_parent_detached);
 ATF_TC_BODY(ptrace__follow_fork_parent_detached, tc)
 {
 	pid_t children[2], fpid, wpid;
 	int status;
 
 	ATF_REQUIRE((fpid = fork()) != -1);
 	if (fpid == 0) {
 		trace_me();
 		follow_fork_parent(false);
 	}
 
 	/* Parent process. */
 	children[0] = fpid;
 
 	/* The first wait() should report the stop from SIGSTOP. */
 	wpid = waitpid(children[0], &status, 0);
 	ATF_REQUIRE(wpid == children[0]);
 	ATF_REQUIRE(WIFSTOPPED(status));
 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
 
 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1);
 
 	/* Continue the child ignoring the SIGSTOP. */
 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
 
 	children[1] = handle_fork_events(children[0], NULL);
 	ATF_REQUIRE(children[1] > 0);
 
 	ATF_REQUIRE(ptrace(PT_DETACH, children[0], (caddr_t)1, 0) != -1);
 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[1], (caddr_t)1, 0) != -1);
 
 	/*
 	 * The child can't exit until the grandchild reports status, so the
 	 * grandchild should report its exit first to the debugger.
 	 *
 	 * Even though the child process is detached, it is still a
 	 * child of the debugger, so it will still report it's exit
 	 * after the grandchild.
 	 */
 	wpid = wait(&status);
 	ATF_REQUIRE(wpid == children[1]);
 	ATF_REQUIRE(WIFEXITED(status));
 	ATF_REQUIRE(WEXITSTATUS(status) == 2);
 
 	wpid = wait(&status);
 	ATF_REQUIRE(wpid == children[0]);
 	ATF_REQUIRE(WIFEXITED(status));
 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
 
 	wpid = wait(&status);
 	ATF_REQUIRE(wpid == -1);
 	ATF_REQUIRE(errno == ECHILD);
 }
 
 static void
 attach_fork_parent(int cpipe[2])
 {
 	pid_t fpid;
 
 	close(cpipe[0]);
 
 	/* Double-fork to disassociate from the debugger. */
 	CHILD_REQUIRE((fpid = fork()) != -1);
 	if (fpid != 0)
 		_exit(3);
 	
 	/* Send the pid of the disassociated child to the debugger. */
 	fpid = getpid();
 	CHILD_REQUIRE(write(cpipe[1], &fpid, sizeof(fpid)) == sizeof(fpid));
 
 	/* Wait for the debugger to attach. */
 	CHILD_REQUIRE(read(cpipe[1], &fpid, sizeof(fpid)) == 0);
 }
 
 /*
  * Verify that a new child process is stopped after a followed fork and
  * that the traced parent sees the exit of the child after the debugger
  * when both processes remain attached to the debugger.  In this test
  * the parent that forks is not a direct child of the debugger.
  */
 ATF_TC_WITHOUT_HEAD(ptrace__follow_fork_both_attached_unrelated_debugger);
 ATF_TC_BODY(ptrace__follow_fork_both_attached_unrelated_debugger, tc)
 {
 	pid_t children[2], fpid, wpid;
 	int cpipe[2], status;
 
 	ATF_REQUIRE(pipe(cpipe) == 0);
 	ATF_REQUIRE((fpid = fork()) != -1);
 	if (fpid == 0) {
 		attach_fork_parent(cpipe);
 		follow_fork_parent(false);
 	}
 
 	/* Parent process. */
 	close(cpipe[1]);
 
 	/* Wait for the direct child to exit. */
 	wpid = waitpid(fpid, &status, 0);
 	ATF_REQUIRE(wpid == fpid);
 	ATF_REQUIRE(WIFEXITED(status));
 	ATF_REQUIRE(WEXITSTATUS(status) == 3);
 
 	/* Read the pid of the fork parent. */
 	ATF_REQUIRE(read(cpipe[0], &children[0], sizeof(children[0])) ==
 	    sizeof(children[0]));
 
 	/* Attach to the fork parent. */
 	attach_child(children[0]);
 
 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1);
 
 	/* Continue the fork parent ignoring the SIGSTOP. */
 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
 
 	/* Signal the fork parent to continue. */
 	close(cpipe[0]);
 
 	children[1] = handle_fork_events(children[0], NULL);
 	ATF_REQUIRE(children[1] > 0);
 
 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[1], (caddr_t)1, 0) != -1);
 
 	/*
 	 * The fork parent can't exit until the child reports status,
 	 * so the child should report its exit first to the debugger.
 	 */
 	wpid = wait(&status);
 	ATF_REQUIRE(wpid == children[1]);
 	ATF_REQUIRE(WIFEXITED(status));
 	ATF_REQUIRE(WEXITSTATUS(status) == 2);
 
 	wpid = wait(&status);
 	ATF_REQUIRE(wpid == children[0]);
 	ATF_REQUIRE(WIFEXITED(status));
 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
 
 	wpid = wait(&status);
 	ATF_REQUIRE(wpid == -1);
 	ATF_REQUIRE(errno == ECHILD);
 }
 
 /*
  * Verify that a new child process is stopped after a followed fork
  * and that the traced parent sees the exit of the child when the new
  * child process is detached after it reports its fork.  In this test
  * the parent that forks is not a direct child of the debugger.
  */
 ATF_TC_WITHOUT_HEAD(ptrace__follow_fork_child_detached_unrelated_debugger);
 ATF_TC_BODY(ptrace__follow_fork_child_detached_unrelated_debugger, tc)
 {
 	pid_t children[2], fpid, wpid;
 	int cpipe[2], status;
 
 	ATF_REQUIRE(pipe(cpipe) == 0);
 	ATF_REQUIRE((fpid = fork()) != -1);
 	if (fpid == 0) {
 		attach_fork_parent(cpipe);
 		follow_fork_parent(false);
 	}
 
 	/* Parent process. */
 	close(cpipe[1]);
 
 	/* Wait for the direct child to exit. */
 	wpid = waitpid(fpid, &status, 0);
 	ATF_REQUIRE(wpid == fpid);
 	ATF_REQUIRE(WIFEXITED(status));
 	ATF_REQUIRE(WEXITSTATUS(status) == 3);
 
 	/* Read the pid of the fork parent. */
 	ATF_REQUIRE(read(cpipe[0], &children[0], sizeof(children[0])) ==
 	    sizeof(children[0]));
 
 	/* Attach to the fork parent. */
 	attach_child(children[0]);
 
 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1);
 
 	/* Continue the fork parent ignoring the SIGSTOP. */
 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
 
 	/* Signal the fork parent to continue. */
 	close(cpipe[0]);
 
 	children[1] = handle_fork_events(children[0], NULL);
 	ATF_REQUIRE(children[1] > 0);
 
 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
 	ATF_REQUIRE(ptrace(PT_DETACH, children[1], (caddr_t)1, 0) != -1);
 
 	/*
 	 * Should not see any status from the child now, only the fork
 	 * parent.
 	 */
 	wpid = wait(&status);
 	ATF_REQUIRE(wpid == children[0]);
 	ATF_REQUIRE(WIFEXITED(status));
 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
 
 	wpid = wait(&status);
 	ATF_REQUIRE(wpid == -1);
 	ATF_REQUIRE(errno == ECHILD);
 }
 
 /*
  * Verify that a new child process is stopped after a followed fork
  * and that the traced parent sees the exit of the child when the
  * traced parent is detached after the fork.  In this test the parent
  * that forks is not a direct child of the debugger.
  */
 ATF_TC_WITHOUT_HEAD(ptrace__follow_fork_parent_detached_unrelated_debugger);
 ATF_TC_BODY(ptrace__follow_fork_parent_detached_unrelated_debugger, tc)
 {
 	pid_t children[2], fpid, wpid;
 	int cpipe[2], status;
 
 	ATF_REQUIRE(pipe(cpipe) == 0);
 	ATF_REQUIRE((fpid = fork()) != -1);
 	if (fpid == 0) {
 		attach_fork_parent(cpipe);
 		follow_fork_parent(false);
 	}
 
 	/* Parent process. */
 	close(cpipe[1]);
 
 	/* Wait for the direct child to exit. */
 	wpid = waitpid(fpid, &status, 0);
 	ATF_REQUIRE(wpid == fpid);
 	ATF_REQUIRE(WIFEXITED(status));
 	ATF_REQUIRE(WEXITSTATUS(status) == 3);
 
 	/* Read the pid of the fork parent. */
 	ATF_REQUIRE(read(cpipe[0], &children[0], sizeof(children[0])) ==
 	    sizeof(children[0]));
 
 	/* Attach to the fork parent. */
 	attach_child(children[0]);
 
 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1);
 
 	/* Continue the fork parent ignoring the SIGSTOP. */
 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
 
 	/* Signal the fork parent to continue. */
 	close(cpipe[0]);
 
 	children[1] = handle_fork_events(children[0], NULL);
 	ATF_REQUIRE(children[1] > 0);
 
 	ATF_REQUIRE(ptrace(PT_DETACH, children[0], (caddr_t)1, 0) != -1);
 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[1], (caddr_t)1, 0) != -1);
 
 	/*
 	 * Should not see any status from the fork parent now, only
 	 * the child.
 	 */
 	wpid = wait(&status);
 	ATF_REQUIRE(wpid == children[1]);
 	ATF_REQUIRE(WIFEXITED(status));
 	ATF_REQUIRE(WEXITSTATUS(status) == 2);
 
 	wpid = wait(&status);
 	ATF_REQUIRE(wpid == -1);
 	ATF_REQUIRE(errno == ECHILD);
 }
 
 /*
  * Verify that a child process does not see an unrelated debugger as its
  * parent but sees its original parent process.
  */
 ATF_TC_WITHOUT_HEAD(ptrace__getppid);
 ATF_TC_BODY(ptrace__getppid, tc)
 {
 	pid_t child, debugger, ppid, wpid;
 	int cpipe[2], dpipe[2], status;
 	char c;
 
 	ATF_REQUIRE(pipe(cpipe) == 0);
 	ATF_REQUIRE((child = fork()) != -1);
 
 	if (child == 0) {
 		/* Child process. */
 		close(cpipe[0]);
 
 		/* Wait for parent to be ready. */
 		CHILD_REQUIRE(read(cpipe[1], &c, sizeof(c)) == sizeof(c));
 
 		/* Report the parent PID to the parent. */
 		ppid = getppid();
 		CHILD_REQUIRE(write(cpipe[1], &ppid, sizeof(ppid)) ==
 		    sizeof(ppid));
 
 		_exit(1);
 	}
 	close(cpipe[1]);
 
 	ATF_REQUIRE(pipe(dpipe) == 0);
 	ATF_REQUIRE((debugger = fork()) != -1);
 
 	if (debugger == 0) {
 		/* Debugger process. */
 		close(dpipe[0]);
 
 		CHILD_REQUIRE(ptrace(PT_ATTACH, child, NULL, 0) != -1);
 
 		wpid = waitpid(child, &status, 0);
 		CHILD_REQUIRE(wpid == child);
 		CHILD_REQUIRE(WIFSTOPPED(status));
 		CHILD_REQUIRE(WSTOPSIG(status) == SIGSTOP);
 
 		CHILD_REQUIRE(ptrace(PT_CONTINUE, child, (caddr_t)1, 0) != -1);
 
 		/* Signal parent that debugger is attached. */
 		CHILD_REQUIRE(write(dpipe[1], &c, sizeof(c)) == sizeof(c));
 
 		/* Wait for traced child to exit. */
 		wpid = waitpid(child, &status, 0);
 		CHILD_REQUIRE(wpid == child);
 		CHILD_REQUIRE(WIFEXITED(status));
 		CHILD_REQUIRE(WEXITSTATUS(status) == 1);
 
 		_exit(0);
 	}
 	close(dpipe[1]);
 
 	/* Parent process. */
 
 	/* Wait for the debugger to attach to the child. */
 	ATF_REQUIRE(read(dpipe[0], &c, sizeof(c)) == sizeof(c));
 
 	/* Release the child. */
 	ATF_REQUIRE(write(cpipe[0], &c, sizeof(c)) == sizeof(c));
 
 	/* Read the parent PID from the child. */
 	ATF_REQUIRE(read(cpipe[0], &ppid, sizeof(ppid)) == sizeof(ppid));
 	close(cpipe[0]);
 
 	ATF_REQUIRE(ppid == getpid());
 
 	/* Wait for the debugger. */
 	wpid = waitpid(debugger, &status, 0);
 	ATF_REQUIRE(wpid == debugger);
 	ATF_REQUIRE(WIFEXITED(status));
 	ATF_REQUIRE(WEXITSTATUS(status) == 0);
 
 	/* The child process should now be ready. */
 	wpid = waitpid(child, &status, WNOHANG);
 	ATF_REQUIRE(wpid == child);
 	ATF_REQUIRE(WIFEXITED(status));
 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
 }
 
 /*
  * Verify that pl_syscall_code in struct ptrace_lwpinfo for a new
  * child process created via fork() reports the correct value.
  */
 ATF_TC_WITHOUT_HEAD(ptrace__new_child_pl_syscall_code_fork);
 ATF_TC_BODY(ptrace__new_child_pl_syscall_code_fork, tc)
 {
 	struct ptrace_lwpinfo pl[2];
 	pid_t children[2], fpid, wpid;
 	int status;
 
 	ATF_REQUIRE((fpid = fork()) != -1);
 	if (fpid == 0) {
 		trace_me();
 		follow_fork_parent(false);
 	}
 
 	/* Parent process. */
 	children[0] = fpid;
 
 	/* The first wait() should report the stop from SIGSTOP. */
 	wpid = waitpid(children[0], &status, 0);
 	ATF_REQUIRE(wpid == children[0]);
 	ATF_REQUIRE(WIFSTOPPED(status));
 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
 
 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1);
 
 	/* Continue the child ignoring the SIGSTOP. */
 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
 
 	/* Wait for both halves of the fork event to get reported. */
 	children[1] = handle_fork_events(children[0], pl);
 	ATF_REQUIRE(children[1] > 0);
 
 	ATF_REQUIRE((pl[0].pl_flags & PL_FLAG_SCX) != 0);
 	ATF_REQUIRE((pl[1].pl_flags & PL_FLAG_SCX) != 0);
 	ATF_REQUIRE(pl[0].pl_syscall_code == SYS_fork);
 	ATF_REQUIRE(pl[0].pl_syscall_code == pl[1].pl_syscall_code);
 	ATF_REQUIRE(pl[0].pl_syscall_narg == pl[1].pl_syscall_narg);
 
 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[1], (caddr_t)1, 0) != -1);
 
 	/*
 	 * The child can't exit until the grandchild reports status, so the
 	 * grandchild should report its exit first to the debugger.
 	 */
 	wpid = wait(&status);
 	ATF_REQUIRE(wpid == children[1]);
 	ATF_REQUIRE(WIFEXITED(status));
 	ATF_REQUIRE(WEXITSTATUS(status) == 2);
 
 	wpid = wait(&status);
 	ATF_REQUIRE(wpid == children[0]);
 	ATF_REQUIRE(WIFEXITED(status));
 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
 
 	wpid = wait(&status);
 	ATF_REQUIRE(wpid == -1);
 	ATF_REQUIRE(errno == ECHILD);
 }
 
 /*
  * Verify that pl_syscall_code in struct ptrace_lwpinfo for a new
  * child process created via vfork() reports the correct value.
  */
 ATF_TC_WITHOUT_HEAD(ptrace__new_child_pl_syscall_code_vfork);
 ATF_TC_BODY(ptrace__new_child_pl_syscall_code_vfork, tc)
 {
 	struct ptrace_lwpinfo pl[2];
 	pid_t children[2], fpid, wpid;
 	int status;
 
 	ATF_REQUIRE((fpid = fork()) != -1);
 	if (fpid == 0) {
 		trace_me();
 		follow_fork_parent(true);
 	}
 
 	/* Parent process. */
 	children[0] = fpid;
 
 	/* The first wait() should report the stop from SIGSTOP. */
 	wpid = waitpid(children[0], &status, 0);
 	ATF_REQUIRE(wpid == children[0]);
 	ATF_REQUIRE(WIFSTOPPED(status));
 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
 
 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1);
 
 	/* Continue the child ignoring the SIGSTOP. */
 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
 
 	/* Wait for both halves of the fork event to get reported. */
 	children[1] = handle_fork_events(children[0], pl);
 	ATF_REQUIRE(children[1] > 0);
 
 	ATF_REQUIRE((pl[0].pl_flags & PL_FLAG_SCX) != 0);
 	ATF_REQUIRE((pl[1].pl_flags & PL_FLAG_SCX) != 0);
 	ATF_REQUIRE(pl[0].pl_syscall_code == SYS_vfork);
 	ATF_REQUIRE(pl[0].pl_syscall_code == pl[1].pl_syscall_code);
 	ATF_REQUIRE(pl[0].pl_syscall_narg == pl[1].pl_syscall_narg);
 
 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[1], (caddr_t)1, 0) != -1);
 
 	/*
 	 * The child can't exit until the grandchild reports status, so the
 	 * grandchild should report its exit first to the debugger.
 	 */
 	wpid = wait(&status);
 	ATF_REQUIRE(wpid == children[1]);
 	ATF_REQUIRE(WIFEXITED(status));
 	ATF_REQUIRE(WEXITSTATUS(status) == 2);
 
 	wpid = wait(&status);
 	ATF_REQUIRE(wpid == children[0]);
 	ATF_REQUIRE(WIFEXITED(status));
 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
 
 	wpid = wait(&status);
 	ATF_REQUIRE(wpid == -1);
 	ATF_REQUIRE(errno == ECHILD);
 }
 
 static void *
 simple_thread(void *arg __unused)
 {
 
 	pthread_exit(NULL);
 }
 
 static __dead2 void
 simple_thread_main(void)
 {
 	pthread_t thread;
 
 	CHILD_REQUIRE(pthread_create(&thread, NULL, simple_thread, NULL) == 0);
 	CHILD_REQUIRE(pthread_join(thread, NULL) == 0);
 	exit(1);
 }
 
 /*
  * Verify that pl_syscall_code in struct ptrace_lwpinfo for a new
  * thread reports the correct value.
  */
 ATF_TC_WITHOUT_HEAD(ptrace__new_child_pl_syscall_code_thread);
 ATF_TC_BODY(ptrace__new_child_pl_syscall_code_thread, tc)
 {
 	struct ptrace_lwpinfo pl;
 	pid_t fpid, wpid;
 	lwpid_t mainlwp;
 	int status;
 
 	ATF_REQUIRE((fpid = fork()) != -1);
 	if (fpid == 0) {
 		trace_me();
 		simple_thread_main();
 	}
 
 	/* The first wait() should report the stop from SIGSTOP. */
 	wpid = waitpid(fpid, &status, 0);
 	ATF_REQUIRE(wpid == fpid);
 	ATF_REQUIRE(WIFSTOPPED(status));
 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
 
 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
 	    sizeof(pl)) != -1);
 	mainlwp = pl.pl_lwpid;
 
 	/*
 	 * Continue the child ignoring the SIGSTOP and tracing all
 	 * system call exits.
 	 */
 	ATF_REQUIRE(ptrace(PT_TO_SCX, fpid, (caddr_t)1, 0) != -1);
 
 	/*
 	 * Wait for the new thread to arrive.  pthread_create() might
 	 * invoke any number of system calls.  For now we just wait
 	 * for the new thread to arrive and make sure it reports a
 	 * valid system call code.  If ptrace grows thread event
 	 * reporting then this test can be made more precise.
 	 */
 	for (;;) {
 		wpid = waitpid(fpid, &status, 0);
 		ATF_REQUIRE(wpid == fpid);
 		ATF_REQUIRE(WIFSTOPPED(status));
 		ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
 		
 		ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
 		    sizeof(pl)) != -1);
 		ATF_REQUIRE((pl.pl_flags & PL_FLAG_SCX) != 0);
 		ATF_REQUIRE(pl.pl_syscall_code != 0);
 		if (pl.pl_lwpid != mainlwp)
 			/* New thread seen. */
 			break;
 
 		ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
 	}
 
 	/* Wait for the child to exit. */
 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
 	for (;;) {
 		wpid = waitpid(fpid, &status, 0);
 		ATF_REQUIRE(wpid == fpid);
 		if (WIFEXITED(status))
 			break;
 		
 		ATF_REQUIRE(WIFSTOPPED(status));
 		ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
 		ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
 	}
 		
 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
 
 	wpid = wait(&status);
 	ATF_REQUIRE(wpid == -1);
 	ATF_REQUIRE(errno == ECHILD);
 }
 
 /*
  * Verify that the expected LWP events are reported for a child thread.
  */
 ATF_TC_WITHOUT_HEAD(ptrace__lwp_events);
 ATF_TC_BODY(ptrace__lwp_events, tc)
 {
 	struct ptrace_lwpinfo pl;
 	pid_t fpid, wpid;
 	lwpid_t lwps[2];
 	int status;
 
 	ATF_REQUIRE((fpid = fork()) != -1);
 	if (fpid == 0) {
 		trace_me();
 		simple_thread_main();
 	}
 
 	/* The first wait() should report the stop from SIGSTOP. */
 	wpid = waitpid(fpid, &status, 0);
 	ATF_REQUIRE(wpid == fpid);
 	ATF_REQUIRE(WIFSTOPPED(status));
 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
 
 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
 	    sizeof(pl)) != -1);
 	lwps[0] = pl.pl_lwpid;
 
 	ATF_REQUIRE(ptrace(PT_LWP_EVENTS, wpid, NULL, 1) == 0);
 
 	/* Continue the child ignoring the SIGSTOP. */
 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
 
 	/* The first event should be for the child thread's birth. */
 	wpid = waitpid(fpid, &status, 0);
 	ATF_REQUIRE(wpid == fpid);
 	ATF_REQUIRE(WIFSTOPPED(status));
 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
 		
 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
 	ATF_REQUIRE((pl.pl_flags & (PL_FLAG_BORN | PL_FLAG_SCX)) ==
 	    (PL_FLAG_BORN | PL_FLAG_SCX));
 	ATF_REQUIRE(pl.pl_lwpid != lwps[0]);
 	lwps[1] = pl.pl_lwpid;
 
 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
 
 	/* The next event should be for the child thread's death. */
 	wpid = waitpid(fpid, &status, 0);
 	ATF_REQUIRE(wpid == fpid);
 	ATF_REQUIRE(WIFSTOPPED(status));
 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
 		
 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
 	ATF_REQUIRE((pl.pl_flags & (PL_FLAG_EXITED | PL_FLAG_SCE)) ==
 	    (PL_FLAG_EXITED | PL_FLAG_SCE));
 	ATF_REQUIRE(pl.pl_lwpid == lwps[1]);
 
 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
 
 	/* The last event should be for the child process's exit. */
 	wpid = waitpid(fpid, &status, 0);
 	ATF_REQUIRE(WIFEXITED(status));
 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
 
 	wpid = wait(&status);
 	ATF_REQUIRE(wpid == -1);
 	ATF_REQUIRE(errno == ECHILD);
 }
 
 static void *
 exec_thread(void *arg __unused)
 {
 
 	execl("/usr/bin/true", "true", NULL);
 	exit(127);
 }
 
 static __dead2 void
 exec_thread_main(void)
 {
 	pthread_t thread;
 
 	CHILD_REQUIRE(pthread_create(&thread, NULL, exec_thread, NULL) == 0);
 	for (;;)
 		sleep(60);
 	exit(1);
 }
 
 /*
  * Verify that the expected LWP events are reported for a multithreaded
  * process that calls execve(2).
  */
 ATF_TC_WITHOUT_HEAD(ptrace__lwp_events_exec);
 ATF_TC_BODY(ptrace__lwp_events_exec, tc)
 {
 	struct ptrace_lwpinfo pl;
 	pid_t fpid, wpid;
 	lwpid_t lwps[2];
 	int status;
 
 	ATF_REQUIRE((fpid = fork()) != -1);
 	if (fpid == 0) {
 		trace_me();
 		exec_thread_main();
 	}
 
 	/* The first wait() should report the stop from SIGSTOP. */
 	wpid = waitpid(fpid, &status, 0);
 	ATF_REQUIRE(wpid == fpid);
 	ATF_REQUIRE(WIFSTOPPED(status));
 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
 
 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
 	    sizeof(pl)) != -1);
 	lwps[0] = pl.pl_lwpid;
 
 	ATF_REQUIRE(ptrace(PT_LWP_EVENTS, wpid, NULL, 1) == 0);
 
 	/* Continue the child ignoring the SIGSTOP. */
 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
 
 	/* The first event should be for the child thread's birth. */
 	wpid = waitpid(fpid, &status, 0);
 	ATF_REQUIRE(wpid == fpid);
 	ATF_REQUIRE(WIFSTOPPED(status));
 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
 		
 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
 	ATF_REQUIRE((pl.pl_flags & (PL_FLAG_BORN | PL_FLAG_SCX)) ==
 	    (PL_FLAG_BORN | PL_FLAG_SCX));
 	ATF_REQUIRE(pl.pl_lwpid != lwps[0]);
 	lwps[1] = pl.pl_lwpid;
 
 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
 
 	/*
 	 * The next event should be for the main thread's death due to
 	 * single threading from execve().
 	 */
 	wpid = waitpid(fpid, &status, 0);
 	ATF_REQUIRE(wpid == fpid);
 	ATF_REQUIRE(WIFSTOPPED(status));
 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
 
 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
 	ATF_REQUIRE((pl.pl_flags & (PL_FLAG_EXITED | PL_FLAG_SCE)) ==
 	    (PL_FLAG_EXITED));
 	ATF_REQUIRE(pl.pl_lwpid == lwps[0]);
 
 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
 
 	/* The next event should be for the child process's exec. */
 	wpid = waitpid(fpid, &status, 0);
 	ATF_REQUIRE(WIFSTOPPED(status));
 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
 
 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
 	ATF_REQUIRE((pl.pl_flags & (PL_FLAG_EXEC | PL_FLAG_SCX)) ==
 	    (PL_FLAG_EXEC | PL_FLAG_SCX));
 	ATF_REQUIRE(pl.pl_lwpid == lwps[1]);
 
 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
 
 	/* The last event should be for the child process's exit. */
 	wpid = waitpid(fpid, &status, 0);
 	ATF_REQUIRE(WIFEXITED(status));
 	ATF_REQUIRE(WEXITSTATUS(status) == 0);
 
 	wpid = wait(&status);
 	ATF_REQUIRE(wpid == -1);
 	ATF_REQUIRE(errno == ECHILD);
 }
 
 static void
 handler(int sig __unused)
 {
 }
 
 static void
 signal_main(void)
 {
 
 	signal(SIGINFO, handler);
 	raise(SIGINFO);
 	exit(0);
 }
 
 /*
  * Verify that the expected ptrace event is reported for a signal.
  */
 ATF_TC_WITHOUT_HEAD(ptrace__siginfo);
 ATF_TC_BODY(ptrace__siginfo, tc)
 {
 	struct ptrace_lwpinfo pl;
 	pid_t fpid, wpid;
 	int status;
 
 	ATF_REQUIRE((fpid = fork()) != -1);
 	if (fpid == 0) {
 		trace_me();
 		signal_main();
 	}
 
 	/* The first wait() should report the stop from SIGSTOP. */
 	wpid = waitpid(fpid, &status, 0);
 	ATF_REQUIRE(wpid == fpid);
 	ATF_REQUIRE(WIFSTOPPED(status));
 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
 
 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
 
 	/* The next event should be for the SIGINFO. */
 	wpid = waitpid(fpid, &status, 0);
 	ATF_REQUIRE(WIFSTOPPED(status));
 	ATF_REQUIRE(WSTOPSIG(status) == SIGINFO);
 
 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
 	ATF_REQUIRE(pl.pl_event == PL_EVENT_SIGNAL);
 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SI);
 	ATF_REQUIRE(pl.pl_siginfo.si_code == SI_LWP);
 	ATF_REQUIRE(pl.pl_siginfo.si_pid == wpid);
 
 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
 
 	/* The last event should be for the child process's exit. */
 	wpid = waitpid(fpid, &status, 0);
 	ATF_REQUIRE(WIFEXITED(status));
 	ATF_REQUIRE(WEXITSTATUS(status) == 0);
 
 	wpid = wait(&status);
 	ATF_REQUIRE(wpid == -1);
 	ATF_REQUIRE(errno == ECHILD);
 }
 
 /*
  * Verify that the expected ptrace events are reported for PTRACE_EXEC.
  */
 ATF_TC_WITHOUT_HEAD(ptrace__ptrace_exec_disable);
 ATF_TC_BODY(ptrace__ptrace_exec_disable, tc)
 {
 	pid_t fpid, wpid;
 	int events, status;
 
 	ATF_REQUIRE((fpid = fork()) != -1);
 	if (fpid == 0) {
 		trace_me();
 		exec_thread(NULL);
 	}
 
 	/* The first wait() should report the stop from SIGSTOP. */
 	wpid = waitpid(fpid, &status, 0);
 	ATF_REQUIRE(wpid == fpid);
 	ATF_REQUIRE(WIFSTOPPED(status));
 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
 
 	events = 0;
 	ATF_REQUIRE(ptrace(PT_SET_EVENT_MASK, fpid, (caddr_t)&events,
 	    sizeof(events)) == 0);
 
 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
 
 	/* Should get one event at exit. */
 	wpid = waitpid(fpid, &status, 0);
 	ATF_REQUIRE(WIFEXITED(status));
 	ATF_REQUIRE(WEXITSTATUS(status) == 0);
 
 	wpid = wait(&status);
 	ATF_REQUIRE(wpid == -1);
 	ATF_REQUIRE(errno == ECHILD);
 }
 
 ATF_TC_WITHOUT_HEAD(ptrace__ptrace_exec_enable);
 ATF_TC_BODY(ptrace__ptrace_exec_enable, tc)
 {
 	struct ptrace_lwpinfo pl;
 	pid_t fpid, wpid;
 	int events, status;
 
 	ATF_REQUIRE((fpid = fork()) != -1);
 	if (fpid == 0) {
 		trace_me();
 		exec_thread(NULL);
 	}
 
 	/* The first wait() should report the stop from SIGSTOP. */
 	wpid = waitpid(fpid, &status, 0);
 	ATF_REQUIRE(wpid == fpid);
 	ATF_REQUIRE(WIFSTOPPED(status));
 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
 
 	events = PTRACE_EXEC;
 	ATF_REQUIRE(ptrace(PT_SET_EVENT_MASK, fpid, (caddr_t)&events,
 	    sizeof(events)) == 0);
 
 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
 
 	/* The next event should be for the child process's exec. */
 	wpid = waitpid(fpid, &status, 0);
 	ATF_REQUIRE(WIFSTOPPED(status));
 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
 
 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
 	ATF_REQUIRE((pl.pl_flags & (PL_FLAG_EXEC | PL_FLAG_SCX)) ==
 	    (PL_FLAG_EXEC | PL_FLAG_SCX));
 
 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
 
 	/* The last event should be for the child process's exit. */
 	wpid = waitpid(fpid, &status, 0);
 	ATF_REQUIRE(WIFEXITED(status));
 	ATF_REQUIRE(WEXITSTATUS(status) == 0);
 
 	wpid = wait(&status);
 	ATF_REQUIRE(wpid == -1);
 	ATF_REQUIRE(errno == ECHILD);
 }
 
 ATF_TC_WITHOUT_HEAD(ptrace__event_mask);
 ATF_TC_BODY(ptrace__event_mask, tc)
 {
 	pid_t fpid, wpid;
 	int events, status;
 
 	ATF_REQUIRE((fpid = fork()) != -1);
 	if (fpid == 0) {
 		trace_me();
 		exit(0);
 	}
 
 	/* The first wait() should report the stop from SIGSTOP. */
 	wpid = waitpid(fpid, &status, 0);
 	ATF_REQUIRE(wpid == fpid);
 	ATF_REQUIRE(WIFSTOPPED(status));
 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
 
 	/* PT_FOLLOW_FORK should toggle the state of PTRACE_FORK. */
 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, fpid, NULL, 1) != -1);
 	ATF_REQUIRE(ptrace(PT_GET_EVENT_MASK, fpid, (caddr_t)&events,
 	    sizeof(events)) == 0);
 	ATF_REQUIRE(events & PTRACE_FORK);
 	ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, fpid, NULL, 0) != -1);
 	ATF_REQUIRE(ptrace(PT_GET_EVENT_MASK, fpid, (caddr_t)&events,
 	    sizeof(events)) == 0);
 	ATF_REQUIRE(!(events & PTRACE_FORK));
 
 	/* PT_LWP_EVENTS should toggle the state of PTRACE_LWP. */
 	ATF_REQUIRE(ptrace(PT_LWP_EVENTS, fpid, NULL, 1) != -1);
 	ATF_REQUIRE(ptrace(PT_GET_EVENT_MASK, fpid, (caddr_t)&events,
 	    sizeof(events)) == 0);
 	ATF_REQUIRE(events & PTRACE_LWP);
 	ATF_REQUIRE(ptrace(PT_LWP_EVENTS, fpid, NULL, 0) != -1);
 	ATF_REQUIRE(ptrace(PT_GET_EVENT_MASK, fpid, (caddr_t)&events,
 	    sizeof(events)) == 0);
 	ATF_REQUIRE(!(events & PTRACE_LWP));
 
 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
 
 	/* Should get one event at exit. */
 	wpid = waitpid(fpid, &status, 0);
 	ATF_REQUIRE(WIFEXITED(status));
 	ATF_REQUIRE(WEXITSTATUS(status) == 0);
 
 	wpid = wait(&status);
 	ATF_REQUIRE(wpid == -1);
 	ATF_REQUIRE(errno == ECHILD);
 }
 
 /*
  * Verify that the expected ptrace events are reported for PTRACE_VFORK.
  */
 ATF_TC_WITHOUT_HEAD(ptrace__ptrace_vfork);
 ATF_TC_BODY(ptrace__ptrace_vfork, tc)
 {
 	struct ptrace_lwpinfo pl;
 	pid_t fpid, wpid;
 	int events, status;
 
 	ATF_REQUIRE((fpid = fork()) != -1);
 	if (fpid == 0) {
 		trace_me();
 		follow_fork_parent(true);
 	}
 
 	/* The first wait() should report the stop from SIGSTOP. */
 	wpid = waitpid(fpid, &status, 0);
 	ATF_REQUIRE(wpid == fpid);
 	ATF_REQUIRE(WIFSTOPPED(status));
 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
 
 	ATF_REQUIRE(ptrace(PT_GET_EVENT_MASK, fpid, (caddr_t)&events,
 	    sizeof(events)) == 0);
 	events |= PTRACE_VFORK;
 	ATF_REQUIRE(ptrace(PT_SET_EVENT_MASK, fpid, (caddr_t)&events,
 	    sizeof(events)) == 0);
 	
 	/* Continue the child ignoring the SIGSTOP. */
 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) != -1);
 
 	/* The next event should report the end of the vfork. */
 	wpid = wait(&status);
 	ATF_REQUIRE(wpid == fpid);
 	ATF_REQUIRE(WIFSTOPPED(status));
 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
 	ATF_REQUIRE((pl.pl_flags & PL_FLAG_VFORK_DONE) != 0);
 
 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) != -1);
 
 	wpid = wait(&status);
 	ATF_REQUIRE(wpid == fpid);
 	ATF_REQUIRE(WIFEXITED(status));
 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
 
 	wpid = wait(&status);
 	ATF_REQUIRE(wpid == -1);
 	ATF_REQUIRE(errno == ECHILD);
 }
 
 ATF_TC_WITHOUT_HEAD(ptrace__ptrace_vfork_follow);
 ATF_TC_BODY(ptrace__ptrace_vfork_follow, tc)
 {
 	struct ptrace_lwpinfo pl[2];
 	pid_t children[2], fpid, wpid;
 	int events, status;
 
 	ATF_REQUIRE((fpid = fork()) != -1);
 	if (fpid == 0) {
 		trace_me();
 		follow_fork_parent(true);
 	}
 
 	/* Parent process. */
 	children[0] = fpid;
 
 	/* The first wait() should report the stop from SIGSTOP. */
 	wpid = waitpid(children[0], &status, 0);
 	ATF_REQUIRE(wpid == children[0]);
 	ATF_REQUIRE(WIFSTOPPED(status));
 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
 
 	ATF_REQUIRE(ptrace(PT_GET_EVENT_MASK, children[0], (caddr_t)&events,
 	    sizeof(events)) == 0);
 	events |= PTRACE_FORK | PTRACE_VFORK;
 	ATF_REQUIRE(ptrace(PT_SET_EVENT_MASK, children[0], (caddr_t)&events,
 	    sizeof(events)) == 0);
 
 	/* Continue the child ignoring the SIGSTOP. */
 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
 
 	/* Wait for both halves of the fork event to get reported. */
 	children[1] = handle_fork_events(children[0], pl);
 	ATF_REQUIRE(children[1] > 0);
 
 	ATF_REQUIRE((pl[0].pl_flags & PL_FLAG_VFORKED) != 0);
 
 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[1], (caddr_t)1, 0) != -1);
 
 	/*
 	 * The child can't exit until the grandchild reports status, so the
 	 * grandchild should report its exit first to the debugger.
 	 */
 	wpid = waitpid(children[1], &status, 0);
 	ATF_REQUIRE(wpid == children[1]);
 	ATF_REQUIRE(WIFEXITED(status));
 	ATF_REQUIRE(WEXITSTATUS(status) == 2);
 
 	/*
 	 * The child should report it's vfork() completion before it
 	 * exits.
 	 */
 	wpid = wait(&status);
 	ATF_REQUIRE(wpid == children[0]);
 	ATF_REQUIRE(WIFSTOPPED(status));
 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl[0], sizeof(pl[0])) !=
 	    -1);
 	ATF_REQUIRE((pl[0].pl_flags & PL_FLAG_VFORK_DONE) != 0);
 
 	ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
 
 	wpid = wait(&status);
 	ATF_REQUIRE(wpid == children[0]);
 	ATF_REQUIRE(WIFEXITED(status));
 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
 
 	wpid = wait(&status);
 	ATF_REQUIRE(wpid == -1);
 	ATF_REQUIRE(errno == ECHILD);
 }
 
 #ifdef HAVE_BREAKPOINT
 /*
  * Verify that no more events are reported after PT_KILL except for the
  * process exit when stopped due to a breakpoint trap.
  */
 ATF_TC_WITHOUT_HEAD(ptrace__PT_KILL_breakpoint);
 ATF_TC_BODY(ptrace__PT_KILL_breakpoint, tc)
 {
 	pid_t fpid, wpid;
 	int status;
 
 	ATF_REQUIRE((fpid = fork()) != -1);
 	if (fpid == 0) {
 		trace_me();
 		breakpoint();
 		exit(1);
 	}
 
 	/* The first wait() should report the stop from SIGSTOP. */
 	wpid = waitpid(fpid, &status, 0);
 	ATF_REQUIRE(wpid == fpid);
 	ATF_REQUIRE(WIFSTOPPED(status));
 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
 
 	/* Continue the child ignoring the SIGSTOP. */
 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
 
 	/* The second wait() should report hitting the breakpoint. */
 	wpid = waitpid(fpid, &status, 0);
 	ATF_REQUIRE(wpid == fpid);
 	ATF_REQUIRE(WIFSTOPPED(status));
 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
 
 	/* Kill the child process. */
 	ATF_REQUIRE(ptrace(PT_KILL, fpid, 0, 0) == 0);
 
 	/* The last wait() should report the SIGKILL. */
 	wpid = waitpid(fpid, &status, 0);
 	ATF_REQUIRE(wpid == fpid);
 	ATF_REQUIRE(WIFSIGNALED(status));
 	ATF_REQUIRE(WTERMSIG(status) == SIGKILL);
 
 	wpid = wait(&status);
 	ATF_REQUIRE(wpid == -1);
 	ATF_REQUIRE(errno == ECHILD);
 }
 #endif /* HAVE_BREAKPOINT */
 
 /*
  * Verify that no more events are reported after PT_KILL except for the
  * process exit when stopped inside of a system call.
  */
 ATF_TC_WITHOUT_HEAD(ptrace__PT_KILL_system_call);
 ATF_TC_BODY(ptrace__PT_KILL_system_call, tc)
 {
 	struct ptrace_lwpinfo pl;
 	pid_t fpid, wpid;
 	int status;
 
 	ATF_REQUIRE((fpid = fork()) != -1);
 	if (fpid == 0) {
 		trace_me();
 		getpid();
 		exit(1);
 	}
 
 	/* The first wait() should report the stop from SIGSTOP. */
 	wpid = waitpid(fpid, &status, 0);
 	ATF_REQUIRE(wpid == fpid);
 	ATF_REQUIRE(WIFSTOPPED(status));
 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
 
 	/* Continue the child ignoring the SIGSTOP and tracing system calls. */
 	ATF_REQUIRE(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0) == 0);
 
 	/* The second wait() should report a system call entry for getpid(). */
 	wpid = waitpid(fpid, &status, 0);
 	ATF_REQUIRE(wpid == fpid);
 	ATF_REQUIRE(WIFSTOPPED(status));
 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
 
 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCE);
 
 	/* Kill the child process. */
 	ATF_REQUIRE(ptrace(PT_KILL, fpid, 0, 0) == 0);
 
 	/* The last wait() should report the SIGKILL. */
 	wpid = waitpid(fpid, &status, 0);
 	ATF_REQUIRE(wpid == fpid);
 	ATF_REQUIRE(WIFSIGNALED(status));
 	ATF_REQUIRE(WTERMSIG(status) == SIGKILL);
 
 	wpid = wait(&status);
 	ATF_REQUIRE(wpid == -1);
 	ATF_REQUIRE(errno == ECHILD);
 }
 
 /*
  * Verify that no more events are reported after PT_KILL except for the
  * process exit when killing a multithreaded process.
  */
 ATF_TC_WITHOUT_HEAD(ptrace__PT_KILL_threads);
 ATF_TC_BODY(ptrace__PT_KILL_threads, tc)
 {
 	struct ptrace_lwpinfo pl;
 	pid_t fpid, wpid;
 	lwpid_t main_lwp;
 	int status;
 
 	ATF_REQUIRE((fpid = fork()) != -1);
 	if (fpid == 0) {
 		trace_me();
 		simple_thread_main();
 	}
 
 	/* The first wait() should report the stop from SIGSTOP. */
 	wpid = waitpid(fpid, &status, 0);
 	ATF_REQUIRE(wpid == fpid);
 	ATF_REQUIRE(WIFSTOPPED(status));
 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
 
 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
 	    sizeof(pl)) != -1);
 	main_lwp = pl.pl_lwpid;
 
 	ATF_REQUIRE(ptrace(PT_LWP_EVENTS, wpid, NULL, 1) == 0);
 
 	/* Continue the child ignoring the SIGSTOP. */
 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
 
 	/* The first event should be for the child thread's birth. */
 	wpid = waitpid(fpid, &status, 0);
 	ATF_REQUIRE(wpid == fpid);
 	ATF_REQUIRE(WIFSTOPPED(status));
 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
 		
 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
 	ATF_REQUIRE((pl.pl_flags & (PL_FLAG_BORN | PL_FLAG_SCX)) ==
 	    (PL_FLAG_BORN | PL_FLAG_SCX));
 	ATF_REQUIRE(pl.pl_lwpid != main_lwp);
 
 	/* Kill the child process. */
 	ATF_REQUIRE(ptrace(PT_KILL, fpid, 0, 0) == 0);
 
 	/* The last wait() should report the SIGKILL. */
 	wpid = waitpid(fpid, &status, 0);
 	ATF_REQUIRE(wpid == fpid);
 	ATF_REQUIRE(WIFSIGNALED(status));
 	ATF_REQUIRE(WTERMSIG(status) == SIGKILL);
 
 	wpid = wait(&status);
 	ATF_REQUIRE(wpid == -1);
 	ATF_REQUIRE(errno == ECHILD);
 }
 
 static void *
 mask_usr1_thread(void *arg)
 {
 	pthread_barrier_t *pbarrier;
 	sigset_t sigmask;
 
 	pbarrier = (pthread_barrier_t*)arg;
 
 	sigemptyset(&sigmask);
 	sigaddset(&sigmask, SIGUSR1);
 	CHILD_REQUIRE(pthread_sigmask(SIG_BLOCK, &sigmask, NULL) == 0);
 
 	/* Sync up with other thread after sigmask updated. */
 	pthread_barrier_wait(pbarrier);
 
 	for (;;)
 		sleep(60);
 
 	return (NULL);
 }
 
 /*
  * Verify that the SIGKILL from PT_KILL takes priority over other signals
  * and prevents spurious stops due to those other signals.
  */
 ATF_TC(ptrace__PT_KILL_competing_signal);
 ATF_TC_HEAD(ptrace__PT_KILL_competing_signal, tc)
 {
 
 	atf_tc_set_md_var(tc, "require.user", "root");
 }
 ATF_TC_BODY(ptrace__PT_KILL_competing_signal, tc)
 {
 	pid_t fpid, wpid;
 	int status;
 	cpuset_t setmask;
 	pthread_t t;
 	pthread_barrier_t barrier;
 	struct sched_param sched_param;
 
 	ATF_REQUIRE((fpid = fork()) != -1);
 	if (fpid == 0) {
 		/* Bind to one CPU so only one thread at a time will run. */
 		CPU_ZERO(&setmask);
 		CPU_SET(0, &setmask);
 		cpusetid_t setid;
 		CHILD_REQUIRE(cpuset(&setid) == 0);
 		CHILD_REQUIRE(cpuset_setaffinity(CPU_LEVEL_CPUSET,
 		    CPU_WHICH_CPUSET, setid, sizeof(setmask), &setmask) == 0);
 
 		CHILD_REQUIRE(pthread_barrier_init(&barrier, NULL, 2) == 0);
 
 		CHILD_REQUIRE(pthread_create(&t, NULL, mask_usr1_thread,
 		    (void*)&barrier) == 0);
 
 		/*
 		 * Give the main thread higher priority. The test always
 		 * assumes that, if both threads are able to run, the main
 		 * thread runs first.
 		 */
 		sched_param.sched_priority =
 		    (sched_get_priority_max(SCHED_FIFO) +
 		    sched_get_priority_min(SCHED_FIFO)) / 2;
 		CHILD_REQUIRE(pthread_setschedparam(pthread_self(),
 		    SCHED_FIFO, &sched_param) == 0);
 		sched_param.sched_priority -= RQ_PPQ;
 		CHILD_REQUIRE(pthread_setschedparam(t, SCHED_FIFO,
 		    &sched_param) == 0);
 
 		sigset_t sigmask;
 		sigemptyset(&sigmask);
 		sigaddset(&sigmask, SIGUSR2);
 		CHILD_REQUIRE(pthread_sigmask(SIG_BLOCK, &sigmask, NULL) == 0);
 
 		/* Sync up with other thread after sigmask updated. */
 		pthread_barrier_wait(&barrier);
 
 		trace_me();
 
 		for (;;)
 			sleep(60);
 
 		exit(1);
 	}
 
 	/* The first wait() should report the stop from SIGSTOP. */
 	wpid = waitpid(fpid, &status, 0);
 	ATF_REQUIRE(wpid == fpid);
 	ATF_REQUIRE(WIFSTOPPED(status));
 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
 
 	/* Continue the child ignoring the SIGSTOP. */
 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
 
 	/* Send a signal that only the second thread can handle. */
 	ATF_REQUIRE(kill(fpid, SIGUSR2) == 0);
 
 	/* The second wait() should report the SIGUSR2. */
 	wpid = waitpid(fpid, &status, 0);
 	ATF_REQUIRE(wpid == fpid);
 	ATF_REQUIRE(WIFSTOPPED(status));
 	ATF_REQUIRE(WSTOPSIG(status) == SIGUSR2);
 
 	/* Send a signal that only the first thread can handle. */
 	ATF_REQUIRE(kill(fpid, SIGUSR1) == 0);
 
 	/* Replace the SIGUSR2 with a kill. */
 	ATF_REQUIRE(ptrace(PT_KILL, fpid, 0, 0) == 0);
 
 	/* The last wait() should report the SIGKILL (not the SIGUSR signal). */
 	wpid = waitpid(fpid, &status, 0);
 	ATF_REQUIRE(wpid == fpid);
 	ATF_REQUIRE(WIFSIGNALED(status));
 	ATF_REQUIRE(WTERMSIG(status) == SIGKILL);
 
 	wpid = wait(&status);
 	ATF_REQUIRE(wpid == -1);
 	ATF_REQUIRE(errno == ECHILD);
 }
 
 /*
  * Verify that the SIGKILL from PT_KILL takes priority over other stop events
  * and prevents spurious stops caused by those events.
  */
 ATF_TC(ptrace__PT_KILL_competing_stop);
 ATF_TC_HEAD(ptrace__PT_KILL_competing_stop, tc)
 {
 
 	atf_tc_set_md_var(tc, "require.user", "root");
 }
 ATF_TC_BODY(ptrace__PT_KILL_competing_stop, tc)
 {
 	pid_t fpid, wpid;
 	int status;
 	cpuset_t setmask;
 	pthread_t t;
 	pthread_barrier_t barrier;
 	lwpid_t main_lwp;
 	struct ptrace_lwpinfo pl;
 	struct sched_param sched_param;
 
 	ATF_REQUIRE((fpid = fork()) != -1);
 	if (fpid == 0) {
 		trace_me();
 
 		/* Bind to one CPU so only one thread at a time will run. */
 		CPU_ZERO(&setmask);
 		CPU_SET(0, &setmask);
 		cpusetid_t setid;
 		CHILD_REQUIRE(cpuset(&setid) == 0);
 		CHILD_REQUIRE(cpuset_setaffinity(CPU_LEVEL_CPUSET,
 		    CPU_WHICH_CPUSET, setid, sizeof(setmask), &setmask) == 0);
 
 		CHILD_REQUIRE(pthread_barrier_init(&barrier, NULL, 2) == 0);
 
 		CHILD_REQUIRE(pthread_create(&t, NULL, mask_usr1_thread,
 		    (void*)&barrier) == 0);
 
 		/*
 		 * Give the main thread higher priority. The test always
 		 * assumes that, if both threads are able to run, the main
 		 * thread runs first.
 		 */
 		sched_param.sched_priority =
 		    (sched_get_priority_max(SCHED_FIFO) +
 		    sched_get_priority_min(SCHED_FIFO)) / 2;
 		CHILD_REQUIRE(pthread_setschedparam(pthread_self(),
 		    SCHED_FIFO, &sched_param) == 0);
 		sched_param.sched_priority -= RQ_PPQ;
 		CHILD_REQUIRE(pthread_setschedparam(t, SCHED_FIFO,
 		    &sched_param) == 0);
 
 		sigset_t sigmask;
 		sigemptyset(&sigmask);
 		sigaddset(&sigmask, SIGUSR2);
 		CHILD_REQUIRE(pthread_sigmask(SIG_BLOCK, &sigmask, NULL) == 0);
 
 		/* Sync up with other thread after sigmask updated. */
 		pthread_barrier_wait(&barrier);
 
 		/* Sync up with the test before doing the getpid(). */
 		raise(SIGSTOP);
 
 		getpid();
 		exit(1);
 	}
 
 	/* The first wait() should report the stop from SIGSTOP. */
 	wpid = waitpid(fpid, &status, 0);
 	ATF_REQUIRE(wpid == fpid);
 	ATF_REQUIRE(WIFSTOPPED(status));
 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
 
 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
 	main_lwp = pl.pl_lwpid;
 
 	/* Continue the child ignoring the SIGSTOP and tracing system calls. */
 	ATF_REQUIRE(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0) == 0);
 
 	/*
 	 * Continue until child is done with setup, which is indicated with
 	 * SIGSTOP. Ignore system calls in the meantime.
 	 */
 	for (;;) {
 		wpid = waitpid(fpid, &status, 0);
 		ATF_REQUIRE(wpid == fpid);
 		ATF_REQUIRE(WIFSTOPPED(status));
 		if (WSTOPSIG(status) == SIGTRAP) {
 			ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
 			    sizeof(pl)) != -1);
 			ATF_REQUIRE(pl.pl_flags & (PL_FLAG_SCE | PL_FLAG_SCX));
 		} else {
 			ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
 			break;
 		}
 		ATF_REQUIRE(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0) == 0);
 	}
 
 	/* Proceed, allowing main thread to hit syscall entry for getpid(). */
 	ATF_REQUIRE(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0) == 0);
 
 	wpid = waitpid(fpid, &status, 0);
 	ATF_REQUIRE(wpid == fpid);
 	ATF_REQUIRE(WIFSTOPPED(status));
 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
 
 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
 	    sizeof(pl)) != -1);
 	ATF_REQUIRE(pl.pl_lwpid == main_lwp);
 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCE);
 	/* Prevent the main thread from hitting its syscall exit for now. */
 	ATF_REQUIRE(ptrace(PT_SUSPEND, main_lwp, 0, 0) == 0);
 
 	/*
 	 * Proceed, allowing second thread to hit syscall exit for
 	 * pthread_barrier_wait().
 	 */
 	ATF_REQUIRE(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0) == 0);
 
 	wpid = waitpid(fpid, &status, 0);
 	ATF_REQUIRE(wpid == fpid);
 	ATF_REQUIRE(WIFSTOPPED(status));
 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
 
 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
 	    sizeof(pl)) != -1);
 	ATF_REQUIRE(pl.pl_lwpid != main_lwp);
 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCX);
 
 	/* Send a signal that only the second thread can handle. */
 	ATF_REQUIRE(kill(fpid, SIGUSR2) == 0);
 
 	ATF_REQUIRE(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0) == 0);
 
 	/* The next wait() should report the SIGUSR2. */
 	wpid = waitpid(fpid, &status, 0);
 	ATF_REQUIRE(wpid == fpid);
 	ATF_REQUIRE(WIFSTOPPED(status));
 	ATF_REQUIRE(WSTOPSIG(status) == SIGUSR2);
 
 	/* Allow the main thread to try to finish its system call. */
 	ATF_REQUIRE(ptrace(PT_RESUME, main_lwp, 0, 0) == 0);
 
 	/*
 	 * At this point, the main thread is in the middle of a system call and
 	 * has been resumed. The second thread has taken a SIGUSR2 which will
 	 * be replaced with a SIGKILL below. The main thread will get to run
 	 * first. It should notice the kill request (even though the signal
 	 * replacement occurred in the other thread) and exit accordingly.  It
 	 * should not stop for the system call exit event.
 	 */
 
 	/* Replace the SIGUSR2 with a kill. */
 	ATF_REQUIRE(ptrace(PT_KILL, fpid, 0, 0) == 0);
 
 	/* The last wait() should report the SIGKILL (not a syscall exit). */
 	wpid = waitpid(fpid, &status, 0);
 	ATF_REQUIRE(wpid == fpid);
 	ATF_REQUIRE(WIFSIGNALED(status));
 	ATF_REQUIRE(WTERMSIG(status) == SIGKILL);
 
 	wpid = wait(&status);
 	ATF_REQUIRE(wpid == -1);
 	ATF_REQUIRE(errno == ECHILD);
 }
 
 static void
 sigusr1_handler(int sig)
 {
 
 	CHILD_REQUIRE(sig == SIGUSR1);
 	_exit(2);
 }
 
 /*
  * Verify that even if the signal queue is full for a child process,
  * a PT_KILL will kill the process.
  */
 ATF_TC_WITHOUT_HEAD(ptrace__PT_KILL_with_signal_full_sigqueue);
 ATF_TC_BODY(ptrace__PT_KILL_with_signal_full_sigqueue, tc)
 {
 	pid_t fpid, wpid;
 	int status;
 	int max_pending_per_proc;
 	size_t len;
 	int i;
 
 	ATF_REQUIRE(signal(SIGUSR1, sigusr1_handler) != SIG_ERR);
 
 	ATF_REQUIRE((fpid = fork()) != -1);
 	if (fpid == 0) {
 		trace_me();
 		exit(1);
 	}
 
 	/* The first wait() should report the stop from SIGSTOP. */
 	wpid = waitpid(fpid, &status, 0);
 	ATF_REQUIRE(wpid == fpid);
 	ATF_REQUIRE(WIFSTOPPED(status));
 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
 
 	len = sizeof(max_pending_per_proc);
 	ATF_REQUIRE(sysctlbyname("kern.sigqueue.max_pending_per_proc",
 	    &max_pending_per_proc, &len, NULL, 0) == 0);
 
 	/* Fill the signal queue. */
 	for (i = 0; i < max_pending_per_proc; ++i)
 		ATF_REQUIRE(kill(fpid, SIGUSR1) == 0);
 
 	/* Kill the child process. */
 	ATF_REQUIRE(ptrace(PT_KILL, fpid, 0, 0) == 0);
 
 	/* The last wait() should report the SIGKILL. */
 	wpid = waitpid(fpid, &status, 0);
 	ATF_REQUIRE(wpid == fpid);
 	ATF_REQUIRE(WIFSIGNALED(status));
 	ATF_REQUIRE(WTERMSIG(status) == SIGKILL);
 
 	wpid = wait(&status);
 	ATF_REQUIRE(wpid == -1);
 	ATF_REQUIRE(errno == ECHILD);
 }
 
 /*
  * Verify that when stopped at a system call entry, a signal can be
  * requested with PT_CONTINUE which will be delivered once the system
  * call is complete.
  */
 ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_with_signal_system_call_entry);
 ATF_TC_BODY(ptrace__PT_CONTINUE_with_signal_system_call_entry, tc)
 {
 	struct ptrace_lwpinfo pl;
 	pid_t fpid, wpid;
 	int status;
 
 	ATF_REQUIRE(signal(SIGUSR1, sigusr1_handler) != SIG_ERR);
 
 	ATF_REQUIRE((fpid = fork()) != -1);
 	if (fpid == 0) {
 		trace_me();
 		getpid();
 		exit(1);
 	}
 
 	/* The first wait() should report the stop from SIGSTOP. */
 	wpid = waitpid(fpid, &status, 0);
 	ATF_REQUIRE(wpid == fpid);
 	ATF_REQUIRE(WIFSTOPPED(status));
 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
 
 	/* Continue the child ignoring the SIGSTOP and tracing system calls. */
 	ATF_REQUIRE(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0) == 0);
 
 	/* The second wait() should report a system call entry for getpid(). */
 	wpid = waitpid(fpid, &status, 0);
 	ATF_REQUIRE(wpid == fpid);
 	ATF_REQUIRE(WIFSTOPPED(status));
 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
 
 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCE);
 
 	/* Continue the child process with a signal. */
 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1) == 0);
 
 	for (;;) {
 		/*
 		 * The last wait() should report exit 2, i.e., a normal _exit
 		 * from the signal handler. In the meantime, catch and proceed
 		 * past any syscall stops.
 		 */
 		wpid = waitpid(fpid, &status, 0);
 		ATF_REQUIRE(wpid == fpid);
 		if (WIFSTOPPED(status) && WSTOPSIG(status) == SIGTRAP) {
 			ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
 			ATF_REQUIRE(pl.pl_flags & (PL_FLAG_SCE | PL_FLAG_SCX));
 			ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
 		} else {
 			ATF_REQUIRE(WIFEXITED(status));
 			ATF_REQUIRE(WEXITSTATUS(status) == 2);
 			break;
 		}
 	}
 
 	wpid = wait(&status);
 	ATF_REQUIRE(wpid == -1);
 	ATF_REQUIRE(errno == ECHILD);
 }
 
 static void
 sigusr1_counting_handler(int sig)
 {
 	static int counter = 0;
 
 	CHILD_REQUIRE(sig == SIGUSR1);
 	counter++;
 	if (counter == 2)
 		_exit(2);
 }
 
 /*
  * Verify that, when continuing from a stop at system call entry and exit,
  * a signal can be requested from both stops, and both will be delivered when
  * the system call is complete.
  */
 ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_with_signal_system_call_entry_and_exit);
 ATF_TC_BODY(ptrace__PT_CONTINUE_with_signal_system_call_entry_and_exit, tc)
 {
 	struct ptrace_lwpinfo pl;
 	pid_t fpid, wpid;
 	int status;
 
 	ATF_REQUIRE(signal(SIGUSR1, sigusr1_counting_handler) != SIG_ERR);
 
 	ATF_REQUIRE((fpid = fork()) != -1);
 	if (fpid == 0) {
 		trace_me();
 		getpid();
 		exit(1);
 	}
 
 	/* The first wait() should report the stop from SIGSTOP. */
 	wpid = waitpid(fpid, &status, 0);
 	ATF_REQUIRE(wpid == fpid);
 	ATF_REQUIRE(WIFSTOPPED(status));
 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
 
 	/* Continue the child ignoring the SIGSTOP and tracing system calls. */
 	ATF_REQUIRE(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0) == 0);
 
 	/* The second wait() should report a system call entry for getpid(). */
 	wpid = waitpid(fpid, &status, 0);
 	ATF_REQUIRE(wpid == fpid);
 	ATF_REQUIRE(WIFSTOPPED(status));
 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
 
 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCE);
 
 	/* Continue the child process with a signal. */
 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1) == 0);
 
 	/* The third wait() should report a system call exit for getpid(). */
 	wpid = waitpid(fpid, &status, 0);
 	ATF_REQUIRE(wpid == fpid);
 	ATF_REQUIRE(WIFSTOPPED(status));
 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
 
 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCX);
 
 	/* Continue the child process with a signal. */
 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1) == 0);
 
 	for (;;) {
 		/*
 		 * The last wait() should report exit 2, i.e., a normal _exit
 		 * from the signal handler. In the meantime, catch and proceed
 		 * past any syscall stops.
 		 */
 		wpid = waitpid(fpid, &status, 0);
 		ATF_REQUIRE(wpid == fpid);
 		if (WIFSTOPPED(status) && WSTOPSIG(status) == SIGTRAP) {
 			ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
 			ATF_REQUIRE(pl.pl_flags & (PL_FLAG_SCE | PL_FLAG_SCX));
 			ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
 		} else {
 			ATF_REQUIRE(WIFEXITED(status));
 			ATF_REQUIRE(WEXITSTATUS(status) == 2);
 			break;
 		}
 	}
 
 	wpid = wait(&status);
 	ATF_REQUIRE(wpid == -1);
 	ATF_REQUIRE(errno == ECHILD);
 }
 
 /*
  * Verify that even if the signal queue is full for a child process,
  * a PT_CONTINUE with a signal will not result in loss of that signal.
  */
 ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_with_signal_full_sigqueue);
 ATF_TC_BODY(ptrace__PT_CONTINUE_with_signal_full_sigqueue, tc)
 {
 	pid_t fpid, wpid;
 	int status;
 	int max_pending_per_proc;
 	size_t len;
 	int i;
 
 	ATF_REQUIRE(signal(SIGUSR2, handler) != SIG_ERR);
 	ATF_REQUIRE(signal(SIGUSR1, sigusr1_handler) != SIG_ERR);
 
 	ATF_REQUIRE((fpid = fork()) != -1);
 	if (fpid == 0) {
 		trace_me();
 		exit(1);
 	}
 
 	/* The first wait() should report the stop from SIGSTOP. */
 	wpid = waitpid(fpid, &status, 0);
 	ATF_REQUIRE(wpid == fpid);
 	ATF_REQUIRE(WIFSTOPPED(status));
 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
 
 	len = sizeof(max_pending_per_proc);
 	ATF_REQUIRE(sysctlbyname("kern.sigqueue.max_pending_per_proc",
 	    &max_pending_per_proc, &len, NULL, 0) == 0);
 
 	/* Fill the signal queue. */
 	for (i = 0; i < max_pending_per_proc; ++i)
 		ATF_REQUIRE(kill(fpid, SIGUSR2) == 0);
 
 	/* Continue with signal. */
 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1) == 0);
 
 	for (;;) {
 		wpid = waitpid(fpid, &status, 0);
 		ATF_REQUIRE(wpid == fpid);
 		if (WIFSTOPPED(status)) {
 			ATF_REQUIRE(WSTOPSIG(status) == SIGUSR2);
 			ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
 		} else {
 			/*
 			 * The last wait() should report normal _exit from the
 			 * SIGUSR1 handler.
 			 */
 			ATF_REQUIRE(WIFEXITED(status));
 			ATF_REQUIRE(WEXITSTATUS(status) == 2);
 			break;
 		}
 	}
 
 	wpid = wait(&status);
 	ATF_REQUIRE(wpid == -1);
 	ATF_REQUIRE(errno == ECHILD);
 }
 
 static sem_t sigusr1_sem;
 static int got_usr1;
 
 static void
 sigusr1_sempost_handler(int sig __unused)
 {
 
 	got_usr1++;
 	CHILD_REQUIRE(sem_post(&sigusr1_sem) == 0);
 }
 
 /*
  * Verify that even if the signal queue is full for a child process,
  * and the signal is masked, a PT_CONTINUE with a signal will not
  * result in loss of that signal.
  */
 ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_with_signal_masked_full_sigqueue);
 ATF_TC_BODY(ptrace__PT_CONTINUE_with_signal_masked_full_sigqueue, tc)
 {
 	struct ptrace_lwpinfo pl;
 	pid_t fpid, wpid;
 	int status, err;
 	int max_pending_per_proc;
 	size_t len;
 	int i;
 	sigset_t sigmask;
 
 	ATF_REQUIRE(signal(SIGUSR2, handler) != SIG_ERR);
 	ATF_REQUIRE(sem_init(&sigusr1_sem, 0, 0) == 0);
 	ATF_REQUIRE(signal(SIGUSR1, sigusr1_sempost_handler) != SIG_ERR);
 
 	got_usr1 = 0;
 	ATF_REQUIRE((fpid = fork()) != -1);
 	if (fpid == 0) {
 		CHILD_REQUIRE(sigemptyset(&sigmask) == 0);
 		CHILD_REQUIRE(sigaddset(&sigmask, SIGUSR1) == 0);
 		CHILD_REQUIRE(sigprocmask(SIG_BLOCK, &sigmask, NULL) == 0);
 
 		trace_me();
 		CHILD_REQUIRE(got_usr1 == 0);
 
 		/* Allow the pending SIGUSR1 in now. */
 		CHILD_REQUIRE(sigprocmask(SIG_UNBLOCK, &sigmask, NULL) == 0);
 		/* Wait to receive the SIGUSR1. */
 		do {
 			err = sem_wait(&sigusr1_sem);
 			CHILD_REQUIRE(err == 0 || errno == EINTR);
 		} while (err != 0 && errno == EINTR);
 		CHILD_REQUIRE(got_usr1 == 1);
 		exit(1);
 	}
 
 	/* The first wait() should report the stop from SIGSTOP. */
 	wpid = waitpid(fpid, &status, 0);
 	ATF_REQUIRE(wpid == fpid);
 	ATF_REQUIRE(WIFSTOPPED(status));
 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
 
 	len = sizeof(max_pending_per_proc);
 	ATF_REQUIRE(sysctlbyname("kern.sigqueue.max_pending_per_proc",
 	    &max_pending_per_proc, &len, NULL, 0) == 0);
 
 	/* Fill the signal queue. */
 	for (i = 0; i < max_pending_per_proc; ++i)
 		ATF_REQUIRE(kill(fpid, SIGUSR2) == 0);
 
 	/* Continue with signal. */
 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1) == 0);
 
 	/* Collect and ignore all of the SIGUSR2. */
 	for (i = 0; i < max_pending_per_proc; ++i) {
 		wpid = waitpid(fpid, &status, 0);
 		ATF_REQUIRE(wpid == fpid);
 		ATF_REQUIRE(WIFSTOPPED(status));
 		ATF_REQUIRE(WSTOPSIG(status) == SIGUSR2);
 		ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
 	}
 
 	/* Now our PT_CONTINUE'd SIGUSR1 should cause a stop after unmask. */
 	wpid = waitpid(fpid, &status, 0);
 	ATF_REQUIRE(wpid == fpid);
 	ATF_REQUIRE(WIFSTOPPED(status));
 	ATF_REQUIRE(WSTOPSIG(status) == SIGUSR1);
 	ATF_REQUIRE(ptrace(PT_LWPINFO, fpid, (caddr_t)&pl, sizeof(pl)) != -1);
 	ATF_REQUIRE(pl.pl_siginfo.si_signo == SIGUSR1);
 
 	/* Continue the child, ignoring the SIGUSR1. */
 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
 
 	/* The last wait() should report exit after receiving SIGUSR1. */
 	wpid = waitpid(fpid, &status, 0);
 	ATF_REQUIRE(wpid == fpid);
 	ATF_REQUIRE(WIFEXITED(status));
 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
 
 	wpid = wait(&status);
 	ATF_REQUIRE(wpid == -1);
 	ATF_REQUIRE(errno == ECHILD);
 }
 
 /*
  * Verify that, after stopping due to a signal, that signal can be
  * replaced with another signal.
  */
 ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_change_sig);
 ATF_TC_BODY(ptrace__PT_CONTINUE_change_sig, tc)
 {
 	struct ptrace_lwpinfo pl;
 	pid_t fpid, wpid;
 	int status;
 
 	ATF_REQUIRE((fpid = fork()) != -1);
 	if (fpid == 0) {
 		trace_me();
 		sleep(20);
 		exit(1);
 	}
 
 	/* The first wait() should report the stop from SIGSTOP. */
 	wpid = waitpid(fpid, &status, 0);
 	ATF_REQUIRE(wpid == fpid);
 	ATF_REQUIRE(WIFSTOPPED(status));
 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
 
 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
 
 	/* Send a signal without ptrace. */
 	ATF_REQUIRE(kill(fpid, SIGINT) == 0);
 
 	/* The second wait() should report a SIGINT was received. */
 	wpid = waitpid(fpid, &status, 0);
 	ATF_REQUIRE(wpid == fpid);
 	ATF_REQUIRE(WIFSTOPPED(status));
 	ATF_REQUIRE(WSTOPSIG(status) == SIGINT);
 
 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SI);
 	ATF_REQUIRE(pl.pl_siginfo.si_signo == SIGINT);
 
 	/* Continue the child process with a different signal. */
 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGTERM) == 0);
 
 	/*
 	 * The last wait() should report having died due to the new
 	 * signal, SIGTERM.
 	 */
 	wpid = waitpid(fpid, &status, 0);
 	ATF_REQUIRE(wpid == fpid);
 	ATF_REQUIRE(WIFSIGNALED(status));
 	ATF_REQUIRE(WTERMSIG(status) == SIGTERM);
 
 	wpid = wait(&status);
 	ATF_REQUIRE(wpid == -1);
 	ATF_REQUIRE(errno == ECHILD);
 }
 
 /*
  * Verify that a signal can be passed through to the child even when there
  * was no true signal originally. Such cases arise when a SIGTRAP is
  * invented for e.g, system call stops.
  */
 ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_with_sigtrap_system_call_entry);
 ATF_TC_BODY(ptrace__PT_CONTINUE_with_sigtrap_system_call_entry, tc)
 {
 	struct ptrace_lwpinfo pl;
 	struct rlimit rl;
 	pid_t fpid, wpid;
 	int status;
 
 	ATF_REQUIRE((fpid = fork()) != -1);
 	if (fpid == 0) {
 		trace_me();
 		/* SIGTRAP expected to cause exit on syscall entry. */
 		rl.rlim_cur = rl.rlim_max = 0;
 		ATF_REQUIRE(setrlimit(RLIMIT_CORE, &rl) == 0);
 		getpid();
 		exit(1);
 	}
 
 	/* The first wait() should report the stop from SIGSTOP. */
 	wpid = waitpid(fpid, &status, 0);
 	ATF_REQUIRE(wpid == fpid);
 	ATF_REQUIRE(WIFSTOPPED(status));
 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
 
 	/* Continue the child ignoring the SIGSTOP and tracing system calls. */
 	ATF_REQUIRE(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0) == 0);
 
 	/* The second wait() should report a system call entry for getpid(). */
 	wpid = waitpid(fpid, &status, 0);
 	ATF_REQUIRE(wpid == fpid);
 	ATF_REQUIRE(WIFSTOPPED(status));
 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
 
 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCE);
 
 	/* Continue the child process with a SIGTRAP. */
 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGTRAP) == 0);
 
 	for (;;) {
 		/*
 		 * The last wait() should report exit due to SIGTRAP.  In the
 		 * meantime, catch and proceed past any syscall stops.
 		 */
 		wpid = waitpid(fpid, &status, 0);
 		ATF_REQUIRE(wpid == fpid);
 		if (WIFSTOPPED(status) && WSTOPSIG(status) == SIGTRAP) {
 			ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
 			ATF_REQUIRE(pl.pl_flags & (PL_FLAG_SCE | PL_FLAG_SCX));
 			ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
 		} else {
 			ATF_REQUIRE(WIFSIGNALED(status));
 			ATF_REQUIRE(WTERMSIG(status) == SIGTRAP);
 			break;
 		}
 	}
 
 	wpid = wait(&status);
 	ATF_REQUIRE(wpid == -1);
 	ATF_REQUIRE(errno == ECHILD);
 
 }
 
 /*
  * A mixed bag PT_CONTINUE with signal test.
  */
 ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_with_signal_mix);
 ATF_TC_BODY(ptrace__PT_CONTINUE_with_signal_mix, tc)
 {
 	struct ptrace_lwpinfo pl;
 	pid_t fpid, wpid;
 	int status;
 
 	ATF_REQUIRE(signal(SIGUSR1, sigusr1_counting_handler) != SIG_ERR);
 
 	ATF_REQUIRE((fpid = fork()) != -1);
 	if (fpid == 0) {
 		trace_me();
 		getpid();
 		exit(1);
 	}
 
 	/* The first wait() should report the stop from SIGSTOP. */
 	wpid = waitpid(fpid, &status, 0);
 	ATF_REQUIRE(wpid == fpid);
 	ATF_REQUIRE(WIFSTOPPED(status));
 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
 
 	/* Continue the child ignoring the SIGSTOP and tracing system calls. */
 	ATF_REQUIRE(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0) == 0);
 
 	/* The second wait() should report a system call entry for getpid(). */
 	wpid = waitpid(fpid, &status, 0);
 	ATF_REQUIRE(wpid == fpid);
 	ATF_REQUIRE(WIFSTOPPED(status));
 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
 
 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCE);
 
 	/* Continue with the first SIGUSR1. */
 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1) == 0);
 
 	/* The next wait() should report a system call exit for getpid(). */
 	wpid = waitpid(fpid, &status, 0);
 	ATF_REQUIRE(wpid == fpid);
 	ATF_REQUIRE(WIFSTOPPED(status));
 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
 
 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCX);
 
 	/* Send an ABRT without ptrace. */
 	ATF_REQUIRE(kill(fpid, SIGABRT) == 0);
 
 	/* Continue normally. */
 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
 
 	/* The next wait() should report the SIGABRT. */
 	wpid = waitpid(fpid, &status, 0);
 	ATF_REQUIRE(wpid == fpid);
 	ATF_REQUIRE(WIFSTOPPED(status));
 	ATF_REQUIRE(WSTOPSIG(status) == SIGABRT);
 
 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SI);
 	ATF_REQUIRE(pl.pl_siginfo.si_signo == SIGABRT);
 
 	/* Continue, replacing the SIGABRT with another SIGUSR1. */
 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1) == 0);
 
 	for (;;) {
 		/*
 		 * The last wait() should report exit 2, i.e., a normal _exit
 		 * from the signal handler. In the meantime, catch and proceed
 		 * past any syscall stops.
 		 */
 		wpid = waitpid(fpid, &status, 0);
 		ATF_REQUIRE(wpid == fpid);
 		if (WIFSTOPPED(status) && WSTOPSIG(status) == SIGTRAP) {
 			ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
 			ATF_REQUIRE(pl.pl_flags & (PL_FLAG_SCE | PL_FLAG_SCX));
 			ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
 		} else {
 			ATF_REQUIRE(WIFEXITED(status));
 			ATF_REQUIRE(WEXITSTATUS(status) == 2);
 			break;
 		}
 	}
 
 	wpid = wait(&status);
 	ATF_REQUIRE(wpid == -1);
 	ATF_REQUIRE(errno == ECHILD);
 
 }
 
 /*
  * Verify a signal delivered by ptrace is noticed by kevent(2).
  */
 ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_with_signal_kqueue);
 ATF_TC_BODY(ptrace__PT_CONTINUE_with_signal_kqueue, tc)
 {
 	pid_t fpid, wpid;
 	int status, kq, nevents;
 	struct kevent kev;
 
 	ATF_REQUIRE(signal(SIGUSR1, SIG_IGN) != SIG_ERR);
 
 	ATF_REQUIRE((fpid = fork()) != -1);
 	if (fpid == 0) {
 		CHILD_REQUIRE((kq = kqueue()) > 0);
 		EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_ADD, 0, 0, 0);
 		CHILD_REQUIRE(kevent(kq, &kev, 1, NULL, 0, NULL) == 0);
 
 		trace_me();
 
 		for (;;) {
 			nevents = kevent(kq, NULL, 0, &kev, 1, NULL);
 			if (nevents == -1 && errno == EINTR)
 				continue;
 			CHILD_REQUIRE(nevents > 0);
 			CHILD_REQUIRE(kev.filter == EVFILT_SIGNAL);
 			CHILD_REQUIRE(kev.ident == SIGUSR1);
 			break;
 		}
 
 		exit(1);
 	}
 
 	/* The first wait() should report the stop from SIGSTOP. */
 	wpid = waitpid(fpid, &status, 0);
 	ATF_REQUIRE(wpid == fpid);
 	ATF_REQUIRE(WIFSTOPPED(status));
 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
 
 	/* Continue with the SIGUSR1. */
 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1) == 0);
 
 	/*
 	 * The last wait() should report normal exit with code 1.
 	 */
 	wpid = waitpid(fpid, &status, 0);
 	ATF_REQUIRE(wpid == fpid);
 	ATF_REQUIRE(WIFEXITED(status));
 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
 
 	wpid = wait(&status);
 	ATF_REQUIRE(wpid == -1);
 	ATF_REQUIRE(errno == ECHILD);
 }
 
 static void *
 signal_thread(void *arg)
 {
 	int err;
 	sigset_t sigmask;
 
 	pthread_barrier_t *pbarrier = (pthread_barrier_t*)arg;
 
 	/* Wait for this thread to receive a SIGUSR1. */
 	do {
 		err = sem_wait(&sigusr1_sem);
 		CHILD_REQUIRE(err == 0 || errno == EINTR);
 	} while (err != 0 && errno == EINTR);
 
 	/* Free our companion thread from the barrier. */
 	pthread_barrier_wait(pbarrier);
 
 	/*
 	 * Swap ignore duties; the next SIGUSR1 should go to the
 	 * other thread.
 	 */
 	CHILD_REQUIRE(sigemptyset(&sigmask) == 0);
 	CHILD_REQUIRE(sigaddset(&sigmask, SIGUSR1) == 0);
 	CHILD_REQUIRE(pthread_sigmask(SIG_BLOCK, &sigmask, NULL) == 0);
 
 	/* Sync up threads after swapping signal masks. */
 	pthread_barrier_wait(pbarrier);
 
 	/* Wait until our companion has received its SIGUSR1. */
 	pthread_barrier_wait(pbarrier);
 
 	return (NULL);
 }
 
 /*
  * Verify that a traced process with blocked signal received the
  * signal from kill() once unmasked.
  */
 ATF_TC_WITHOUT_HEAD(ptrace__killed_with_sigmask);
 ATF_TC_BODY(ptrace__killed_with_sigmask, tc)
 {
 	struct ptrace_lwpinfo pl;
 	pid_t fpid, wpid;
 	int status, err;
 	sigset_t sigmask;
 
 	ATF_REQUIRE(sem_init(&sigusr1_sem, 0, 0) == 0);
 	ATF_REQUIRE(signal(SIGUSR1, sigusr1_sempost_handler) != SIG_ERR);
 	got_usr1 = 0;
 
 	ATF_REQUIRE((fpid = fork()) != -1);
 	if (fpid == 0) {
 		CHILD_REQUIRE(sigemptyset(&sigmask) == 0);
 		CHILD_REQUIRE(sigaddset(&sigmask, SIGUSR1) == 0);
 		CHILD_REQUIRE(sigprocmask(SIG_BLOCK, &sigmask, NULL) == 0);
 
 		trace_me();
 		CHILD_REQUIRE(got_usr1 == 0);
 
 		/* Allow the pending SIGUSR1 in now. */
 		CHILD_REQUIRE(sigprocmask(SIG_UNBLOCK, &sigmask, NULL) == 0);
 		/* Wait to receive a SIGUSR1. */
 		do {
 			err = sem_wait(&sigusr1_sem);
 			CHILD_REQUIRE(err == 0 || errno == EINTR);
 		} while (err != 0 && errno == EINTR);
 		CHILD_REQUIRE(got_usr1 == 1);
 		exit(1);
 	}
 
 	/* The first wait() should report the stop from SIGSTOP. */
 	wpid = waitpid(fpid, &status, 0);
 	ATF_REQUIRE(wpid == fpid);
 	ATF_REQUIRE(WIFSTOPPED(status));
 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
 	ATF_REQUIRE(ptrace(PT_LWPINFO, fpid, (caddr_t)&pl, sizeof(pl)) != -1);
 	ATF_REQUIRE(pl.pl_siginfo.si_signo == SIGSTOP);
 
 	/* Send blocked SIGUSR1 which should cause a stop. */
 	ATF_REQUIRE(kill(fpid, SIGUSR1) == 0);
 
 	/* Continue the child ignoring the SIGSTOP. */
 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
 
 	/* The next wait() should report the kill(SIGUSR1) was received. */
 	wpid = waitpid(fpid, &status, 0);
 	ATF_REQUIRE(wpid == fpid);
 	ATF_REQUIRE(WIFSTOPPED(status));
 	ATF_REQUIRE(WSTOPSIG(status) == SIGUSR1);
 	ATF_REQUIRE(ptrace(PT_LWPINFO, fpid, (caddr_t)&pl, sizeof(pl)) != -1);
 	ATF_REQUIRE(pl.pl_siginfo.si_signo == SIGUSR1);
 
 	/* Continue the child, allowing in the SIGUSR1. */
 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1) == 0);
 
 	/* The last wait() should report normal exit with code 1. */
 	wpid = waitpid(fpid, &status, 0);
 	ATF_REQUIRE(wpid == fpid);
 	ATF_REQUIRE(WIFEXITED(status));
 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
 
 	wpid = wait(&status);
 	ATF_REQUIRE(wpid == -1);
 	ATF_REQUIRE(errno == ECHILD);
 }
 
 /*
  * Verify that a traced process with blocked signal received the
  * signal from PT_CONTINUE once unmasked.
  */
 ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_with_sigmask);
 ATF_TC_BODY(ptrace__PT_CONTINUE_with_sigmask, tc)
 {
 	struct ptrace_lwpinfo pl;
 	pid_t fpid, wpid;
 	int status, err;
 	sigset_t sigmask;
 
 	ATF_REQUIRE(sem_init(&sigusr1_sem, 0, 0) == 0);
 	ATF_REQUIRE(signal(SIGUSR1, sigusr1_sempost_handler) != SIG_ERR);
 	got_usr1 = 0;
 
 	ATF_REQUIRE((fpid = fork()) != -1);
 	if (fpid == 0) {
 		CHILD_REQUIRE(sigemptyset(&sigmask) == 0);
 		CHILD_REQUIRE(sigaddset(&sigmask, SIGUSR1) == 0);
 		CHILD_REQUIRE(sigprocmask(SIG_BLOCK, &sigmask, NULL) == 0);
 
 		trace_me();
 		CHILD_REQUIRE(got_usr1 == 0);
 
 		/* Allow the pending SIGUSR1 in now. */
 		CHILD_REQUIRE(sigprocmask(SIG_UNBLOCK, &sigmask, NULL) == 0);
 		/* Wait to receive a SIGUSR1. */
 		do {
 			err = sem_wait(&sigusr1_sem);
 			CHILD_REQUIRE(err == 0 || errno == EINTR);
 		} while (err != 0 && errno == EINTR);
 
 		CHILD_REQUIRE(got_usr1 == 1);
 		exit(1);
 	}
 
 	/* The first wait() should report the stop from SIGSTOP. */
 	wpid = waitpid(fpid, &status, 0);
 	ATF_REQUIRE(wpid == fpid);
 	ATF_REQUIRE(WIFSTOPPED(status));
 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
 	ATF_REQUIRE(ptrace(PT_LWPINFO, fpid, (caddr_t)&pl, sizeof(pl)) != -1);
 	ATF_REQUIRE(pl.pl_siginfo.si_signo == SIGSTOP);
 
 	/* Continue the child replacing SIGSTOP with SIGUSR1. */
 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1) == 0);
 
 	/* The next wait() should report the SIGUSR1 was received. */
 	wpid = waitpid(fpid, &status, 0);
 	ATF_REQUIRE(wpid == fpid);
 	ATF_REQUIRE(WIFSTOPPED(status));
 	ATF_REQUIRE(WSTOPSIG(status) == SIGUSR1);
 	ATF_REQUIRE(ptrace(PT_LWPINFO, fpid, (caddr_t)&pl, sizeof(pl)) != -1);
 	ATF_REQUIRE(pl.pl_siginfo.si_signo == SIGUSR1);
 
 	/* Continue the child, ignoring the SIGUSR1. */
 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
 
 	/* The last wait() should report normal exit with code 1. */
 	wpid = waitpid(fpid, &status, 0);
 	ATF_REQUIRE(wpid == fpid);
 	ATF_REQUIRE(WIFEXITED(status));
 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
 
 	wpid = wait(&status);
 	ATF_REQUIRE(wpid == -1);
 	ATF_REQUIRE(errno == ECHILD);
 }
 
 /*
  * Verify that if ptrace stops due to a signal but continues with
  * a different signal that the new signal is routed to a thread
  * that can accept it, and that that thread is awakened by the signal
  * in a timely manner.
  */
 ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_with_signal_thread_sigmask);
 ATF_TC_BODY(ptrace__PT_CONTINUE_with_signal_thread_sigmask, tc)
 {
 	pid_t fpid, wpid;
 	int status, err;
 	pthread_t t;
 	sigset_t sigmask;
 	pthread_barrier_t barrier;
 
 	ATF_REQUIRE(pthread_barrier_init(&barrier, NULL, 2) == 0);
 	ATF_REQUIRE(sem_init(&sigusr1_sem, 0, 0) == 0);
 	ATF_REQUIRE(signal(SIGUSR1, sigusr1_sempost_handler) != SIG_ERR);
 
 	ATF_REQUIRE((fpid = fork()) != -1);
 	if (fpid == 0) {
 		CHILD_REQUIRE(pthread_create(&t, NULL, signal_thread, (void*)&barrier) == 0);
 
 		/* The other thread should receive the first SIGUSR1. */
 		CHILD_REQUIRE(sigemptyset(&sigmask) == 0);
 		CHILD_REQUIRE(sigaddset(&sigmask, SIGUSR1) == 0);
 		CHILD_REQUIRE(pthread_sigmask(SIG_BLOCK, &sigmask, NULL) == 0);
 
 		trace_me();
 
 		/* Wait until other thread has received its SIGUSR1. */
 		pthread_barrier_wait(&barrier);
 
 		/*
 		 * Swap ignore duties; the next SIGUSR1 should go to this
 		 * thread.
 		 */
 		CHILD_REQUIRE(pthread_sigmask(SIG_UNBLOCK, &sigmask, NULL) == 0);
 
 		/* Sync up threads after swapping signal masks. */
 		pthread_barrier_wait(&barrier);
 
 		/*
 		 * Sync up with test code; we're ready for the next SIGUSR1
 		 * now.
 		 */
 		raise(SIGSTOP);
 
 		/* Wait for this thread to receive a SIGUSR1. */
 		do {
 			err = sem_wait(&sigusr1_sem);
 			CHILD_REQUIRE(err == 0 || errno == EINTR);
 		} while (err != 0 && errno == EINTR);
 
 		/* Free the other thread from the barrier. */
 		pthread_barrier_wait(&barrier);
 
 		CHILD_REQUIRE(pthread_join(t, NULL) == 0);
 
 		exit(1);
 	}
 
 	/* The first wait() should report the stop from SIGSTOP. */
 	wpid = waitpid(fpid, &status, 0);
 	ATF_REQUIRE(wpid == fpid);
 	ATF_REQUIRE(WIFSTOPPED(status));
 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
 
 	/* Continue the child ignoring the SIGSTOP. */
 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
 
 	/*
 	 * Send a signal without ptrace that either thread will accept (USR2,
 	 * in this case).
 	 */
 	ATF_REQUIRE(kill(fpid, SIGUSR2) == 0);
 	
 	/* The second wait() should report a SIGUSR2 was received. */
 	wpid = waitpid(fpid, &status, 0);
 	ATF_REQUIRE(wpid == fpid);
 	ATF_REQUIRE(WIFSTOPPED(status));
 	ATF_REQUIRE(WSTOPSIG(status) == SIGUSR2);
 
 	/* Continue the child, changing the signal to USR1. */
 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1) == 0);
 
 	/* The next wait() should report the stop from SIGSTOP. */
 	wpid = waitpid(fpid, &status, 0);
 	ATF_REQUIRE(wpid == fpid);
 	ATF_REQUIRE(WIFSTOPPED(status));
 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
 
 	/* Continue the child ignoring the SIGSTOP. */
 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
 
 	ATF_REQUIRE(kill(fpid, SIGUSR2) == 0);
 
 	/* The next wait() should report a SIGUSR2 was received. */
 	wpid = waitpid(fpid, &status, 0);
 	ATF_REQUIRE(wpid == fpid);
 	ATF_REQUIRE(WIFSTOPPED(status));
 	ATF_REQUIRE(WSTOPSIG(status) == SIGUSR2);
 
 	/* Continue the child, changing the signal to USR1. */
 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1) == 0);
 
 	/* The last wait() should report normal exit with code 1. */
 	wpid = waitpid(fpid, &status, 0);
 	ATF_REQUIRE(wpid == fpid);
 	ATF_REQUIRE(WIFEXITED(status));
 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
 
 	wpid = wait(&status);
 	ATF_REQUIRE(wpid == -1);
 	ATF_REQUIRE(errno == ECHILD);
 }
 
 static void *
 raise_sigstop_thread(void *arg __unused)
 {
 
 	raise(SIGSTOP);
 	return NULL;
 }
 
 static void *
 sleep_thread(void *arg __unused)
 {
 
 	sleep(60);
 	return NULL;
 }
 
 static void
 terminate_with_pending_sigstop(bool sigstop_from_main_thread)
 {
 	pid_t fpid, wpid;
 	int status, i;
 	cpuset_t setmask;
 	cpusetid_t setid;
 	pthread_t t;
 
 	/*
 	 * Become the reaper for this process tree. We need to be able to check
 	 * that both child and grandchild have died.
 	 */
 	ATF_REQUIRE(procctl(P_PID, getpid(), PROC_REAP_ACQUIRE, NULL) == 0);
 
 	fpid = fork();
 	ATF_REQUIRE(fpid >= 0);
 	if (fpid == 0) {
 		fpid = fork();
 		CHILD_REQUIRE(fpid >= 0);
 		if (fpid == 0) {
 			trace_me();
 
 			/* Pin to CPU 0 to serialize thread execution. */
 			CPU_ZERO(&setmask);
 			CPU_SET(0, &setmask);
 			CHILD_REQUIRE(cpuset(&setid) == 0);
 			CHILD_REQUIRE(cpuset_setaffinity(CPU_LEVEL_CPUSET,
 			    CPU_WHICH_CPUSET, setid,
 			    sizeof(setmask), &setmask) == 0);
 
 			if (sigstop_from_main_thread) {
 				/*
 				 * We expect the SIGKILL sent when our parent
 				 * dies to be delivered to the new thread.
 				 * Raise the SIGSTOP in this thread so the
 				 * threads compete.
 				 */
 				CHILD_REQUIRE(pthread_create(&t, NULL,
 				    sleep_thread, NULL) == 0);
 				raise(SIGSTOP);
 			} else {
 				/*
 				 * We expect the SIGKILL to be delivered to
 				 * this thread. After creating the new thread,
 				 * just get off the CPU so the other thread can
 				 * raise the SIGSTOP.
 				 */
 				CHILD_REQUIRE(pthread_create(&t, NULL,
 				    raise_sigstop_thread, NULL) == 0);
 				sleep(60);
 			}
 
 			exit(0);
 		}
 		/* First stop is trace_me() immediately after fork. */
 		wpid = waitpid(fpid, &status, 0);
 		CHILD_REQUIRE(wpid == fpid);
 		CHILD_REQUIRE(WIFSTOPPED(status));
 		CHILD_REQUIRE(WSTOPSIG(status) == SIGSTOP);
 
 		CHILD_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
 
 		/* Second stop is from the raise(SIGSTOP). */
 		wpid = waitpid(fpid, &status, 0);
 		CHILD_REQUIRE(wpid == fpid);
 		CHILD_REQUIRE(WIFSTOPPED(status));
 		CHILD_REQUIRE(WSTOPSIG(status) == SIGSTOP);
 
 		/*
 		 * Terminate tracing process without detaching. Our child
 		 * should be killed.
 		 */
 		exit(0);
 	}
 
 	/*
 	 * We should get a normal exit from our immediate child and a SIGKILL
 	 * exit from our grandchild. The latter case is the interesting one.
 	 * Our grandchild should not have stopped due to the SIGSTOP that was
 	 * left dangling when its parent died.
 	 */
 	for (i = 0; i < 2; ++i) {
 		wpid = wait(&status);
 		if (wpid == fpid)
 			ATF_REQUIRE(WIFEXITED(status) &&
 			    WEXITSTATUS(status) == 0);
 		else
 			ATF_REQUIRE(WIFSIGNALED(status) &&
 			    WTERMSIG(status) == SIGKILL);
 	}
 }
 
 /*
  * These two tests ensure that if the tracing process exits without detaching
  * just after the child received a SIGSTOP, the child is cleanly killed and
  * doesn't go to sleep due to the SIGSTOP. The parent's death will send a
  * SIGKILL to the child. If the SIGKILL and the SIGSTOP are handled by
  * different threads, the SIGKILL must win.  There are two variants of this
  * test, designed to catch the case where the SIGKILL is delivered to the
  * younger thread (the first test) and the case where the SIGKILL is delivered
  * to the older thread (the second test). This behavior has changed in the
  * past, so make no assumption.
  */
 ATF_TC(ptrace__parent_terminate_with_pending_sigstop1);
 ATF_TC_HEAD(ptrace__parent_terminate_with_pending_sigstop1, tc)
 {
 
 	atf_tc_set_md_var(tc, "require.user", "root");
 }
 ATF_TC_BODY(ptrace__parent_terminate_with_pending_sigstop1, tc)
 {
 
 	terminate_with_pending_sigstop(true);
 }
 
 ATF_TC(ptrace__parent_terminate_with_pending_sigstop2);
 ATF_TC_HEAD(ptrace__parent_terminate_with_pending_sigstop2, tc)
 {
 
 	atf_tc_set_md_var(tc, "require.user", "root");
 }
 ATF_TC_BODY(ptrace__parent_terminate_with_pending_sigstop2, tc)
 {
 
 	terminate_with_pending_sigstop(false);
 }
 
 /*
  * Verify that after ptrace() discards a SIGKILL signal, the event mask
  * is not modified.
  */
 ATF_TC_WITHOUT_HEAD(ptrace__event_mask_sigkill_discard);
 ATF_TC_BODY(ptrace__event_mask_sigkill_discard, tc)
 {
 	struct ptrace_lwpinfo pl;
 	pid_t fpid, wpid;
 	int status, event_mask, new_event_mask;
 
 	ATF_REQUIRE((fpid = fork()) != -1);
 	if (fpid == 0) {
 		trace_me();
 		raise(SIGSTOP);
 		exit(0);
 	}
 
 	/* The first wait() should report the stop from trace_me(). */
 	wpid = waitpid(fpid, &status, 0);
 	ATF_REQUIRE(wpid == fpid);
 	ATF_REQUIRE(WIFSTOPPED(status));
 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
 
 	/* Set several unobtrusive event bits. */
 	event_mask = PTRACE_EXEC | PTRACE_FORK | PTRACE_LWP;
 	ATF_REQUIRE(ptrace(PT_SET_EVENT_MASK, wpid, (caddr_t)&event_mask,
 	    sizeof(event_mask)) == 0);
 
 	/* Send a SIGKILL without using ptrace. */
 	ATF_REQUIRE(kill(fpid, SIGKILL) == 0);
 
 	/* Continue the child ignoring the SIGSTOP. */
 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
 
 	/* The next stop should be due to the SIGKILL. */
 	wpid = waitpid(fpid, &status, 0);
 	ATF_REQUIRE(wpid == fpid);
 	ATF_REQUIRE(WIFSTOPPED(status));
 	ATF_REQUIRE(WSTOPSIG(status) == SIGKILL);
 
 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SI);
 	ATF_REQUIRE(pl.pl_siginfo.si_signo == SIGKILL);
 
 	/* Continue the child ignoring the SIGKILL. */
 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
 
 	/* The next wait() should report the stop from SIGSTOP. */
 	wpid = waitpid(fpid, &status, 0);
 	ATF_REQUIRE(wpid == fpid);
 	ATF_REQUIRE(WIFSTOPPED(status));
 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
 
 	/* Check the current event mask. It should not have changed. */
 	new_event_mask = 0;
 	ATF_REQUIRE(ptrace(PT_GET_EVENT_MASK, wpid, (caddr_t)&new_event_mask,
 	    sizeof(new_event_mask)) == 0);
 	ATF_REQUIRE(event_mask == new_event_mask);
 
 	/* Continue the child to let it exit. */
 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
 
 	/* The last event should be for the child process's exit. */
 	wpid = waitpid(fpid, &status, 0);
 	ATF_REQUIRE(WIFEXITED(status));
 	ATF_REQUIRE(WEXITSTATUS(status) == 0);
 
 	wpid = wait(&status);
 	ATF_REQUIRE(wpid == -1);
 	ATF_REQUIRE(errno == ECHILD);
 }
 
 static void *
 flock_thread(void *arg)
 {
 	int fd;
 
 	fd = *(int *)arg;
 	(void)flock(fd, LOCK_EX);
 	(void)flock(fd, LOCK_UN);
 	return (NULL);
 }
 
 /*
  * Verify that PT_ATTACH will suspend threads sleeping in an SBDRY section.
  * We rely on the fact that the lockf implementation sets SBDRY before blocking
  * on a lock. This is a regression test for r318191.
  */
 ATF_TC_WITHOUT_HEAD(ptrace__PT_ATTACH_with_SBDRY_thread);
 ATF_TC_BODY(ptrace__PT_ATTACH_with_SBDRY_thread, tc)
 {
 	pthread_barrier_t barrier;
 	pthread_barrierattr_t battr;
 	char tmpfile[64];
 	pid_t child, wpid;
 	int error, fd, i, status;
 
 	ATF_REQUIRE(pthread_barrierattr_init(&battr) == 0);
 	ATF_REQUIRE(pthread_barrierattr_setpshared(&battr,
 	    PTHREAD_PROCESS_SHARED) == 0);
 	ATF_REQUIRE(pthread_barrier_init(&barrier, &battr, 2) == 0);
 
 	(void)snprintf(tmpfile, sizeof(tmpfile), "./ptrace.XXXXXX");
 	fd = mkstemp(tmpfile);
 	ATF_REQUIRE(fd >= 0);
 
 	ATF_REQUIRE((child = fork()) != -1);
 	if (child == 0) {
 		pthread_t t[2];
 		int cfd;
 
 		error = pthread_barrier_wait(&barrier);
 		if (error != 0 && error != PTHREAD_BARRIER_SERIAL_THREAD)
 			_exit(1);
 
 		cfd = open(tmpfile, O_RDONLY);
 		if (cfd < 0)
 			_exit(1);
 
 		/*
 		 * We want at least two threads blocked on the file lock since
 		 * the SIGSTOP from PT_ATTACH may kick one of them out of
 		 * sleep.
 		 */
 		if (pthread_create(&t[0], NULL, flock_thread, &cfd) != 0)
 			_exit(1);
 		if (pthread_create(&t[1], NULL, flock_thread, &cfd) != 0)
 			_exit(1);
 		if (pthread_join(t[0], NULL) != 0)
 			_exit(1);
 		if (pthread_join(t[1], NULL) != 0)
 			_exit(1);
 		_exit(0);
 	}
 
 	ATF_REQUIRE(flock(fd, LOCK_EX) == 0);
 
 	error = pthread_barrier_wait(&barrier);
 	ATF_REQUIRE(error == 0 || error == PTHREAD_BARRIER_SERIAL_THREAD);
 
 	/*
 	 * Give the child some time to block. Is there a better way to do this?
 	 */
 	sleep(1);
 
 	/*
 	 * Attach and give the child 3 seconds to stop.
 	 */
 	ATF_REQUIRE(ptrace(PT_ATTACH, child, NULL, 0) == 0);
 	for (i = 0; i < 3; i++) {
 		wpid = waitpid(child, &status, WNOHANG);
 		if (wpid == child && WIFSTOPPED(status) &&
 		    WSTOPSIG(status) == SIGSTOP)
 			break;
 		sleep(1);
 	}
 	ATF_REQUIRE_MSG(i < 3, "failed to stop child process after PT_ATTACH");
 
 	ATF_REQUIRE(ptrace(PT_DETACH, child, NULL, 0) == 0);
 
 	ATF_REQUIRE(flock(fd, LOCK_UN) == 0);
 	ATF_REQUIRE(unlink(tmpfile) == 0);
 	ATF_REQUIRE(close(fd) == 0);
 }
 
 static void
 sigusr1_step_handler(int sig)
 {
 
 	CHILD_REQUIRE(sig == SIGUSR1);
 	raise(SIGABRT);
 }
 
 /*
  * Verify that PT_STEP with a signal invokes the signal before
  * stepping the next instruction (and that the next instruction is
  * stepped correctly).
  */
 ATF_TC_WITHOUT_HEAD(ptrace__PT_STEP_with_signal);
 ATF_TC_BODY(ptrace__PT_STEP_with_signal, tc)
 {
 	struct ptrace_lwpinfo pl;
 	pid_t fpid, wpid;
 	int status;
 
 	ATF_REQUIRE((fpid = fork()) != -1);
 	if (fpid == 0) {
 		trace_me();
 		signal(SIGUSR1, sigusr1_step_handler);
 		raise(SIGABRT);
 		exit(1);
 	}
 
 	/* The first wait() should report the stop from SIGSTOP. */
 	wpid = waitpid(fpid, &status, 0);
 	ATF_REQUIRE(wpid == fpid);
 	ATF_REQUIRE(WIFSTOPPED(status));
 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
 
 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
 
 	/* The next stop should report the SIGABRT in the child body. */
 	wpid = waitpid(fpid, &status, 0);
 	ATF_REQUIRE(wpid == fpid);
 	ATF_REQUIRE(WIFSTOPPED(status));
 	ATF_REQUIRE(WSTOPSIG(status) == SIGABRT);
 
 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SI);
 	ATF_REQUIRE(pl.pl_siginfo.si_signo == SIGABRT);
 
 	/* Step the child process inserting SIGUSR1. */
 	ATF_REQUIRE(ptrace(PT_STEP, fpid, (caddr_t)1, SIGUSR1) == 0);
 
 	/* The next stop should report the SIGABRT in the signal handler. */
 	wpid = waitpid(fpid, &status, 0);
 	ATF_REQUIRE(wpid == fpid);
 	ATF_REQUIRE(WIFSTOPPED(status));
 	ATF_REQUIRE(WSTOPSIG(status) == SIGABRT);
 
 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SI);
 	ATF_REQUIRE(pl.pl_siginfo.si_signo == SIGABRT);
 
 	/* Continue the child process discarding the signal. */
 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
 
 	/* The next stop should report a trace trap from PT_STEP. */
 	wpid = waitpid(fpid, &status, 0);
 	ATF_REQUIRE(wpid == fpid);
 	ATF_REQUIRE(WIFSTOPPED(status));
 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
 
 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SI);
 	ATF_REQUIRE(pl.pl_siginfo.si_signo == SIGTRAP);
 	ATF_REQUIRE(pl.pl_siginfo.si_code == TRAP_TRACE);
 
 	/* Continue the child to let it exit. */
 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
 
 	/* The last event should be for the child process's exit. */
 	wpid = waitpid(fpid, &status, 0);
 	ATF_REQUIRE(WIFEXITED(status));
 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
 
 	wpid = wait(&status);
 	ATF_REQUIRE(wpid == -1);
 	ATF_REQUIRE(errno == ECHILD);
 }
 
 #ifdef HAVE_BREAKPOINT
 /*
  * Verify that a SIGTRAP event with the TRAP_BRKPT code is reported
  * for a breakpoint trap.
  */
 ATF_TC_WITHOUT_HEAD(ptrace__breakpoint_siginfo);
 ATF_TC_BODY(ptrace__breakpoint_siginfo, tc)
 {
 	struct ptrace_lwpinfo pl;
 	pid_t fpid, wpid;
 	int status;
 
 	ATF_REQUIRE((fpid = fork()) != -1);
 	if (fpid == 0) {
 		trace_me();
 		breakpoint();
 		exit(1);
 	}
 
 	/* The first wait() should report the stop from SIGSTOP. */
 	wpid = waitpid(fpid, &status, 0);
 	ATF_REQUIRE(wpid == fpid);
 	ATF_REQUIRE(WIFSTOPPED(status));
 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
 
 	/* Continue the child ignoring the SIGSTOP. */
 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
 
 	/* The second wait() should report hitting the breakpoint. */
 	wpid = waitpid(fpid, &status, 0);
 	ATF_REQUIRE(wpid == fpid);
 	ATF_REQUIRE(WIFSTOPPED(status));
 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
 
 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
 	ATF_REQUIRE((pl.pl_flags & PL_FLAG_SI) != 0);
 	ATF_REQUIRE(pl.pl_siginfo.si_signo == SIGTRAP);
 	ATF_REQUIRE(pl.pl_siginfo.si_code == TRAP_BRKPT);
 
 	/* Kill the child process. */
 	ATF_REQUIRE(ptrace(PT_KILL, fpid, 0, 0) == 0);
 
 	/* The last wait() should report the SIGKILL. */
 	wpid = waitpid(fpid, &status, 0);
 	ATF_REQUIRE(wpid == fpid);
 	ATF_REQUIRE(WIFSIGNALED(status));
 	ATF_REQUIRE(WTERMSIG(status) == SIGKILL);
 
 	wpid = wait(&status);
 	ATF_REQUIRE(wpid == -1);
 	ATF_REQUIRE(errno == ECHILD);
 }
 #endif /* HAVE_BREAKPOINT */
 
 /*
  * Verify that a SIGTRAP event with the TRAP_TRACE code is reported
  * for a single-step trap from PT_STEP.
  */
 ATF_TC_WITHOUT_HEAD(ptrace__step_siginfo);
 ATF_TC_BODY(ptrace__step_siginfo, tc)
 {
 	struct ptrace_lwpinfo pl;
 	pid_t fpid, wpid;
 	int status;
 
 	ATF_REQUIRE((fpid = fork()) != -1);
 	if (fpid == 0) {
 		trace_me();
 		exit(1);
 	}
 
 	/* The first wait() should report the stop from SIGSTOP. */
 	wpid = waitpid(fpid, &status, 0);
 	ATF_REQUIRE(wpid == fpid);
 	ATF_REQUIRE(WIFSTOPPED(status));
 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
 
 	/* Step the child ignoring the SIGSTOP. */
 	ATF_REQUIRE(ptrace(PT_STEP, fpid, (caddr_t)1, 0) == 0);
 
 	/* The second wait() should report a single-step trap. */
 	wpid = waitpid(fpid, &status, 0);
 	ATF_REQUIRE(wpid == fpid);
 	ATF_REQUIRE(WIFSTOPPED(status));
 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
 
 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
 	ATF_REQUIRE((pl.pl_flags & PL_FLAG_SI) != 0);
 	ATF_REQUIRE(pl.pl_siginfo.si_signo == SIGTRAP);
 	ATF_REQUIRE(pl.pl_siginfo.si_code == TRAP_TRACE);
 
 	/* Continue the child process. */
 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
 
 	/* The last event should be for the child process's exit. */
 	wpid = waitpid(fpid, &status, 0);
 	ATF_REQUIRE(WIFEXITED(status));
 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
 
 	wpid = wait(&status);
 	ATF_REQUIRE(wpid == -1);
 	ATF_REQUIRE(errno == ECHILD);
 }
 
 #if defined(HAVE_BREAKPOINT) && defined(SKIP_BREAK)
 static void *
 continue_thread(void *arg __unused)
 {
 	breakpoint();
 	return (NULL);
 }
 
 static __dead2 void
 continue_thread_main(void)
 {
 	pthread_t threads[2];
 
 	CHILD_REQUIRE(pthread_create(&threads[0], NULL, continue_thread,
 	    NULL) == 0);
 	CHILD_REQUIRE(pthread_create(&threads[1], NULL, continue_thread,
 	    NULL) == 0);
 	CHILD_REQUIRE(pthread_join(threads[0], NULL) == 0);
 	CHILD_REQUIRE(pthread_join(threads[1], NULL) == 0);
 	exit(1);
 }
 
 /*
  * Ensure that PT_CONTINUE clears the status of the thread that
  * triggered the stop even if a different thread's LWP was passed to
  * PT_CONTINUE.
  */
 ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_different_thread);
 ATF_TC_BODY(ptrace__PT_CONTINUE_different_thread, tc)
 {
 	struct ptrace_lwpinfo pl;
 	pid_t fpid, wpid;
 	lwpid_t lwps[2];
 	bool hit_break[2];
 	struct reg reg;
 	int i, j, status;
 
 	ATF_REQUIRE((fpid = fork()) != -1);
 	if (fpid == 0) {
 		trace_me();
 		continue_thread_main();
 	}
 
 	/* The first wait() should report the stop from SIGSTOP. */
 	wpid = waitpid(fpid, &status, 0);
 	ATF_REQUIRE(wpid == fpid);
 	ATF_REQUIRE(WIFSTOPPED(status));
 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
 
 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
 	    sizeof(pl)) != -1);
 
 	ATF_REQUIRE(ptrace(PT_LWP_EVENTS, wpid, NULL, 1) == 0);
 
 	/* Continue the child ignoring the SIGSTOP. */
 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
 
 	/* One of the new threads should report it's birth. */
 	wpid = waitpid(fpid, &status, 0);
 	ATF_REQUIRE(wpid == fpid);
 	ATF_REQUIRE(WIFSTOPPED(status));
 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
 
 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
 	ATF_REQUIRE((pl.pl_flags & (PL_FLAG_BORN | PL_FLAG_SCX)) ==
 	    (PL_FLAG_BORN | PL_FLAG_SCX));
 	lwps[0] = pl.pl_lwpid;
 
 	/*
 	 * Suspend this thread to ensure both threads are alive before
 	 * hitting the breakpoint.
 	 */
 	ATF_REQUIRE(ptrace(PT_SUSPEND, lwps[0], NULL, 0) != -1);
 
 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
 
 	/* Second thread should report it's birth. */
 	wpid = waitpid(fpid, &status, 0);
 	ATF_REQUIRE(wpid == fpid);
 	ATF_REQUIRE(WIFSTOPPED(status));
 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
 
 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
 	ATF_REQUIRE((pl.pl_flags & (PL_FLAG_BORN | PL_FLAG_SCX)) ==
 	    (PL_FLAG_BORN | PL_FLAG_SCX));
 	ATF_REQUIRE(pl.pl_lwpid != lwps[0]);
 	lwps[1] = pl.pl_lwpid;
 
 	/* Resume both threads waiting for breakpoint events. */
 	hit_break[0] = hit_break[1] = false;
 	ATF_REQUIRE(ptrace(PT_RESUME, lwps[0], NULL, 0) != -1);
 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
 
 	/* One thread should report a breakpoint. */
 	wpid = waitpid(fpid, &status, 0);
 	ATF_REQUIRE(wpid == fpid);
 	ATF_REQUIRE(WIFSTOPPED(status));
 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
 
 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
 	ATF_REQUIRE((pl.pl_flags & PL_FLAG_SI) != 0);
 	ATF_REQUIRE(pl.pl_siginfo.si_signo == SIGTRAP &&
 	    pl.pl_siginfo.si_code == TRAP_BRKPT);
 	if (pl.pl_lwpid == lwps[0])
 		i = 0;
 	else
 		i = 1;
 	hit_break[i] = true;
 	ATF_REQUIRE(ptrace(PT_GETREGS, pl.pl_lwpid, (caddr_t)&reg, 0) != -1);
 	SKIP_BREAK(&reg);
 	ATF_REQUIRE(ptrace(PT_SETREGS, pl.pl_lwpid, (caddr_t)&reg, 0) != -1);
 
 	/*
 	 * Resume both threads but pass the other thread's LWPID to
 	 * PT_CONTINUE.
 	 */
 	ATF_REQUIRE(ptrace(PT_CONTINUE, lwps[i ^ 1], (caddr_t)1, 0) == 0);
 
 	/*
 	 * Will now get two thread exit events and one more breakpoint
 	 * event.
 	 */
 	for (j = 0; j < 3; j++) {
 		wpid = waitpid(fpid, &status, 0);
 		ATF_REQUIRE(wpid == fpid);
 		ATF_REQUIRE(WIFSTOPPED(status));
 		ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
 
 		ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
 		    sizeof(pl)) != -1);
 		
 		if (pl.pl_lwpid == lwps[0])
 			i = 0;
 		else
 			i = 1;
 
 		ATF_REQUIRE_MSG(lwps[i] != 0, "event for exited thread");
 		if (pl.pl_flags & PL_FLAG_EXITED) {
 			ATF_REQUIRE_MSG(hit_break[i],
 			    "exited thread did not report breakpoint");
 			lwps[i] = 0;
 		} else {
 			ATF_REQUIRE((pl.pl_flags & PL_FLAG_SI) != 0);
 			ATF_REQUIRE(pl.pl_siginfo.si_signo == SIGTRAP &&
 			    pl.pl_siginfo.si_code == TRAP_BRKPT);
 			ATF_REQUIRE_MSG(!hit_break[i],
 			    "double breakpoint event");
 			hit_break[i] = true;
 			ATF_REQUIRE(ptrace(PT_GETREGS, pl.pl_lwpid, (caddr_t)&reg,
 			    0) != -1);
 			SKIP_BREAK(&reg);
 			ATF_REQUIRE(ptrace(PT_SETREGS, pl.pl_lwpid, (caddr_t)&reg,
 			    0) != -1);
 		}
 
 		ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
 	}
 
 	/* Both threads should have exited. */
 	ATF_REQUIRE(lwps[0] == 0);
 	ATF_REQUIRE(lwps[1] == 0);
 
 	/* The last event should be for the child process's exit. */
 	wpid = waitpid(fpid, &status, 0);
 	ATF_REQUIRE(WIFEXITED(status));
 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
 
 	wpid = wait(&status);
 	ATF_REQUIRE(wpid == -1);
 	ATF_REQUIRE(errno == ECHILD);
 }
 #endif
 
 /*
  * Verify that PT_LWPINFO doesn't return stale siginfo.
  */
 ATF_TC_WITHOUT_HEAD(ptrace__PT_LWPINFO_stale_siginfo);
 ATF_TC_BODY(ptrace__PT_LWPINFO_stale_siginfo, tc)
 {
 	struct ptrace_lwpinfo pl;
 	pid_t fpid, wpid;
 	int events, status;
 
 	ATF_REQUIRE((fpid = fork()) != -1);
 	if (fpid == 0) {
 		trace_me();
 		raise(SIGABRT);
 		exit(1);
 	}
 
 	/* The first wait() should report the stop from SIGSTOP. */
 	wpid = waitpid(fpid, &status, 0);
 	ATF_REQUIRE(wpid == fpid);
 	ATF_REQUIRE(WIFSTOPPED(status));
 	ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
 
 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
 
 	/* The next stop should report the SIGABRT in the child body. */
 	wpid = waitpid(fpid, &status, 0);
 	ATF_REQUIRE(wpid == fpid);
 	ATF_REQUIRE(WIFSTOPPED(status));
 	ATF_REQUIRE(WSTOPSIG(status) == SIGABRT);
 
 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SI);
 	ATF_REQUIRE(pl.pl_siginfo.si_signo == SIGABRT);
 
 	/*
 	 * Continue the process ignoring the signal, but enabling
 	 * syscall traps.
 	 */
 	ATF_REQUIRE(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0) == 0);
 
 	/*
 	 * The next stop should report a system call entry from
 	 * exit().  PL_FLAGS_SI should not be set.
 	 */
 	wpid = waitpid(fpid, &status, 0);
 	ATF_REQUIRE(wpid == fpid);
 	ATF_REQUIRE(WIFSTOPPED(status));
 	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
 
 	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
 	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCE);
 	ATF_REQUIRE((pl.pl_flags & PL_FLAG_SI) == 0);
 
 	/* Disable syscall tracing and continue the child to let it exit. */
 	ATF_REQUIRE(ptrace(PT_GET_EVENT_MASK, fpid, (caddr_t)&events,
 	    sizeof(events)) == 0);
 	events &= ~PTRACE_SYSCALL;
 	ATF_REQUIRE(ptrace(PT_SET_EVENT_MASK, fpid, (caddr_t)&events,
 	    sizeof(events)) == 0);
 	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
 
 	/* The last event should be for the child process's exit. */
 	wpid = waitpid(fpid, &status, 0);
 	ATF_REQUIRE(WIFEXITED(status));
 	ATF_REQUIRE(WEXITSTATUS(status) == 1);
 
 	wpid = wait(&status);
 	ATF_REQUIRE(wpid == -1);
 	ATF_REQUIRE(errno == ECHILD);
 }
 
 ATF_TP_ADD_TCS(tp)
 {
 
 	ATF_TP_ADD_TC(tp, ptrace__parent_wait_after_trace_me);
 	ATF_TP_ADD_TC(tp, ptrace__parent_wait_after_attach);
 	ATF_TP_ADD_TC(tp, ptrace__parent_sees_exit_after_child_debugger);
 	ATF_TP_ADD_TC(tp, ptrace__parent_sees_exit_after_unrelated_debugger);
+	ATF_TP_ADD_TC(tp, ptrace__parent_exits_before_child);
 	ATF_TP_ADD_TC(tp, ptrace__follow_fork_both_attached);
 	ATF_TP_ADD_TC(tp, ptrace__follow_fork_child_detached);
 	ATF_TP_ADD_TC(tp, ptrace__follow_fork_parent_detached);
 	ATF_TP_ADD_TC(tp, ptrace__follow_fork_both_attached_unrelated_debugger);
 	ATF_TP_ADD_TC(tp,
 	    ptrace__follow_fork_child_detached_unrelated_debugger);
 	ATF_TP_ADD_TC(tp,
 	    ptrace__follow_fork_parent_detached_unrelated_debugger);
 	ATF_TP_ADD_TC(tp, ptrace__getppid);
 	ATF_TP_ADD_TC(tp, ptrace__new_child_pl_syscall_code_fork);
 	ATF_TP_ADD_TC(tp, ptrace__new_child_pl_syscall_code_vfork);
 	ATF_TP_ADD_TC(tp, ptrace__new_child_pl_syscall_code_thread);
 	ATF_TP_ADD_TC(tp, ptrace__lwp_events);
 	ATF_TP_ADD_TC(tp, ptrace__lwp_events_exec);
 	ATF_TP_ADD_TC(tp, ptrace__siginfo);
 	ATF_TP_ADD_TC(tp, ptrace__ptrace_exec_disable);
 	ATF_TP_ADD_TC(tp, ptrace__ptrace_exec_enable);
 	ATF_TP_ADD_TC(tp, ptrace__event_mask);
 	ATF_TP_ADD_TC(tp, ptrace__ptrace_vfork);
 	ATF_TP_ADD_TC(tp, ptrace__ptrace_vfork_follow);
 #ifdef HAVE_BREAKPOINT
 	ATF_TP_ADD_TC(tp, ptrace__PT_KILL_breakpoint);
 #endif
 	ATF_TP_ADD_TC(tp, ptrace__PT_KILL_system_call);
 	ATF_TP_ADD_TC(tp, ptrace__PT_KILL_threads);
 	ATF_TP_ADD_TC(tp, ptrace__PT_KILL_competing_signal);
 	ATF_TP_ADD_TC(tp, ptrace__PT_KILL_competing_stop);
 	ATF_TP_ADD_TC(tp, ptrace__PT_KILL_with_signal_full_sigqueue);
 	ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_with_signal_system_call_entry);
 	ATF_TP_ADD_TC(tp,
 	    ptrace__PT_CONTINUE_with_signal_system_call_entry_and_exit);
 	ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_with_signal_full_sigqueue);
 	ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_with_signal_masked_full_sigqueue);
 	ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_change_sig);
 	ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_with_sigtrap_system_call_entry);
 	ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_with_signal_mix);
 	ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_with_signal_kqueue);
 	ATF_TP_ADD_TC(tp, ptrace__killed_with_sigmask);
 	ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_with_sigmask);
 	ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_with_signal_thread_sigmask);
 	ATF_TP_ADD_TC(tp, ptrace__parent_terminate_with_pending_sigstop1);
 	ATF_TP_ADD_TC(tp, ptrace__parent_terminate_with_pending_sigstop2);
 	ATF_TP_ADD_TC(tp, ptrace__event_mask_sigkill_discard);
 	ATF_TP_ADD_TC(tp, ptrace__PT_ATTACH_with_SBDRY_thread);
 	ATF_TP_ADD_TC(tp, ptrace__PT_STEP_with_signal);
 #ifdef HAVE_BREAKPOINT
 	ATF_TP_ADD_TC(tp, ptrace__breakpoint_siginfo);
 #endif
 	ATF_TP_ADD_TC(tp, ptrace__step_siginfo);
 #if defined(HAVE_BREAKPOINT) && defined(SKIP_BREAK)
 	ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_different_thread);
 #endif
 	ATF_TP_ADD_TC(tp, ptrace__PT_LWPINFO_stale_siginfo);
 
 	return (atf_no_error());
 }
Index: stable/11
===================================================================
--- stable/11	(revision 346540)
+++ stable/11	(revision 346541)

Property changes on: stable/11
___________________________________________________________________
Modified: svn:mergeinfo
## -0,0 +0,1 ##
   Merged /head:r346009