xref: /freebsd/sys/kern/kern_exit.c (revision 69a2875821ed9404a95f41bbeeb561908e3c38dc)
19454b2d8SWarner Losh /*-
2df8bae1dSRodney W. Grimes  * Copyright (c) 1982, 1986, 1989, 1991, 1993
3df8bae1dSRodney W. Grimes  *	The Regents of the University of California.  All rights reserved.
4df8bae1dSRodney W. Grimes  * (c) UNIX System Laboratories, Inc.
5df8bae1dSRodney W. Grimes  * All or some portions of this file are derived from material licensed
6df8bae1dSRodney W. Grimes  * to the University of California by American Telephone and Telegraph
7df8bae1dSRodney W. Grimes  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
8df8bae1dSRodney W. Grimes  * the permission of UNIX System Laboratories, Inc.
9df8bae1dSRodney W. Grimes  *
10df8bae1dSRodney W. Grimes  * Redistribution and use in source and binary forms, with or without
11df8bae1dSRodney W. Grimes  * modification, are permitted provided that the following conditions
12df8bae1dSRodney W. Grimes  * are met:
13df8bae1dSRodney W. Grimes  * 1. Redistributions of source code must retain the above copyright
14df8bae1dSRodney W. Grimes  *    notice, this list of conditions and the following disclaimer.
15df8bae1dSRodney W. Grimes  * 2. Redistributions in binary form must reproduce the above copyright
16df8bae1dSRodney W. Grimes  *    notice, this list of conditions and the following disclaimer in the
17df8bae1dSRodney W. Grimes  *    documentation and/or other materials provided with the distribution.
18*69a28758SEd Maste  * 3. Neither the name of the University nor the names of its contributors
19df8bae1dSRodney W. Grimes  *    may be used to endorse or promote products derived from this software
20df8bae1dSRodney W. Grimes  *    without specific prior written permission.
21df8bae1dSRodney W. Grimes  *
22df8bae1dSRodney W. Grimes  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23df8bae1dSRodney W. Grimes  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24df8bae1dSRodney W. Grimes  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25df8bae1dSRodney W. Grimes  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26df8bae1dSRodney W. Grimes  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27df8bae1dSRodney W. Grimes  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28df8bae1dSRodney W. Grimes  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29df8bae1dSRodney W. Grimes  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30df8bae1dSRodney W. Grimes  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31df8bae1dSRodney W. Grimes  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32df8bae1dSRodney W. Grimes  * SUCH DAMAGE.
33df8bae1dSRodney W. Grimes  *
34df8bae1dSRodney W. Grimes  *	@(#)kern_exit.c	8.7 (Berkeley) 2/12/94
35df8bae1dSRodney W. Grimes  */
36df8bae1dSRodney W. Grimes 
37677b542eSDavid E. O'Brien #include <sys/cdefs.h>
38677b542eSDavid E. O'Brien __FBSDID("$FreeBSD$");
39677b542eSDavid E. O'Brien 
405591b823SEivind Eklund #include "opt_compat.h"
41db6a20e2SGarrett Wollman #include "opt_ktrace.h"
42db6a20e2SGarrett Wollman 
43df8bae1dSRodney W. Grimes #include <sys/param.h>
44df8bae1dSRodney W. Grimes #include <sys/systm.h>
455fdb8324SBruce Evans #include <sys/sysproto.h>
464a144410SRobert Watson #include <sys/capsicum.h>
4775b8b3b2SJohn Baldwin #include <sys/eventhandler.h>
481c5bb3eaSPeter Wemm #include <sys/kernel.h>
49a1c995b6SPoul-Henning Kamp #include <sys/malloc.h>
50f34fa851SJohn Baldwin #include <sys/lock.h>
5135e0e5b3SJohn Baldwin #include <sys/mutex.h>
52df8bae1dSRodney W. Grimes #include <sys/proc.h>
53cfb5f768SJonathan Anderson #include <sys/procdesc.h>
542a024a2bSSean Eric Fagan #include <sys/pioctl.h>
55413628a7SBjoern A. Zeeb #include <sys/jail.h>
56df8bae1dSRodney W. Grimes #include <sys/tty.h>
57df8bae1dSRodney W. Grimes #include <sys/wait.h>
58eb30c1c0SPeter Wemm #include <sys/vmmeter.h>
597a6b989bSJohn Baldwin #include <sys/vnode.h>
60097055e2SEdward Tomasz Napierala #include <sys/racct.h>
61df8bae1dSRodney W. Grimes #include <sys/resourcevar.h>
6225f6e35aSPoul-Henning Kamp #include <sys/sbuf.h>
63797f2d22SPoul-Henning Kamp #include <sys/signalvar.h>
64b43179fbSJeff Roberson #include <sys/sched.h>
651005a129SJohn Baldwin #include <sys/sx.h>
66c8837938SJohn Baldwin #include <sys/syscallsubr.h>
6725f6e35aSPoul-Henning Kamp #include <sys/syslog.h>
68df8bae1dSRodney W. Grimes #include <sys/ptrace.h>
697c409b8aSJeffrey Hsu #include <sys/acct.h>		/* for acct_process() function prototype */
70797f2d22SPoul-Henning Kamp #include <sys/filedesc.h>
715d217f17SJohn Birrell #include <sys/sdt.h>
72780dc5a8SPeter Wemm #include <sys/shm.h>
73780dc5a8SPeter Wemm #include <sys/sem.h>
7413dad108SKonstantin Belousov #include <sys/umtx.h>
756c84de02SJohn Baldwin #ifdef KTRACE
766c84de02SJohn Baldwin #include <sys/ktrace.h>
776c84de02SJohn Baldwin #endif
78780dc5a8SPeter Wemm 
79fcf7f27aSRobert Watson #include <security/audit/audit.h>
80aed55708SRobert Watson #include <security/mac/mac_framework.h>
81fcf7f27aSRobert Watson 
82df8bae1dSRodney W. Grimes #include <vm/vm.h>
83eb30c1c0SPeter Wemm #include <vm/vm_extern.h>
847a6b989bSJohn Baldwin #include <vm/vm_param.h>
85efeaf95aSDavid Greenman #include <vm/pmap.h>
86efeaf95aSDavid Greenman #include <vm/vm_map.h>
872d21129dSAlan Cox #include <vm/vm_page.h>
88c897b813SJeff Roberson #include <vm/uma.h>
896520495aSAdrian Chadd #include <vm/vm_domain.h>
90df8bae1dSRodney W. Grimes 
915d217f17SJohn Birrell #ifdef KDTRACE_HOOKS
925d217f17SJohn Birrell #include <sys/dtrace_bsd.h>
935d217f17SJohn Birrell dtrace_execexit_func_t	dtrace_fasttrap_exit;
945d217f17SJohn Birrell #endif
955d217f17SJohn Birrell 
965d217f17SJohn Birrell SDT_PROVIDER_DECLARE(proc);
9736160958SMark Johnston SDT_PROBE_DEFINE1(proc, , , exit, "int");
985d217f17SJohn Birrell 
99c0bc2867SGleb Smirnoff /* Hook for NFS teardown procedure. */
100c0bc2867SGleb Smirnoff void (*nlminfo_release_p)(struct proc *p);
101c0bc2867SGleb Smirnoff 
102d7359980SKonstantin Belousov struct proc *
103d7359980SKonstantin Belousov proc_realparent(struct proc *child)
104d7359980SKonstantin Belousov {
105d7359980SKonstantin Belousov 	struct proc *p, *parent;
106d7359980SKonstantin Belousov 
107d7359980SKonstantin Belousov 	sx_assert(&proctree_lock, SX_LOCKED);
108d7359980SKonstantin Belousov 	if ((child->p_treeflag & P_TREE_ORPHANED) == 0) {
1099152087eSMateusz Guzik 		if (child->p_oppid == 0 ||
1109152087eSMateusz Guzik 		    child->p_pptr->p_pid == child->p_oppid)
1119152087eSMateusz Guzik 			parent = child->p_pptr;
1129152087eSMateusz Guzik 		else
1139152087eSMateusz Guzik 			parent = initproc;
1149152087eSMateusz Guzik 		return (parent);
115d7359980SKonstantin Belousov 	}
116d7359980SKonstantin Belousov 	for (p = child; (p->p_treeflag & P_TREE_FIRST_ORPHAN) == 0;) {
117d7359980SKonstantin Belousov 		/* Cannot use LIST_PREV(), since the list head is not known. */
118d7359980SKonstantin Belousov 		p = __containerof(p->p_orphan.le_prev, struct proc,
119d7359980SKonstantin Belousov 		    p_orphan.le_next);
120d7359980SKonstantin Belousov 		KASSERT((p->p_treeflag & P_TREE_ORPHANED) != 0,
121d7359980SKonstantin Belousov 		    ("missing P_ORPHAN %p", p));
122d7359980SKonstantin Belousov 	}
123d7359980SKonstantin Belousov 	parent = __containerof(p->p_orphan.le_prev, struct proc,
124d7359980SKonstantin Belousov 	    p_orphans.lh_first);
125d7359980SKonstantin Belousov 	return (parent);
126d7359980SKonstantin Belousov }
127d7359980SKonstantin Belousov 
128237623b0SKonstantin Belousov void
129237623b0SKonstantin Belousov reaper_abandon_children(struct proc *p, bool exiting)
130237623b0SKonstantin Belousov {
131237623b0SKonstantin Belousov 	struct proc *p1, *p2, *ptmp;
132237623b0SKonstantin Belousov 
133237623b0SKonstantin Belousov 	sx_assert(&proctree_lock, SX_LOCKED);
134237623b0SKonstantin Belousov 	KASSERT(p != initproc, ("reaper_abandon_children for initproc"));
135237623b0SKonstantin Belousov 	if ((p->p_treeflag & P_TREE_REAPER) == 0)
136237623b0SKonstantin Belousov 		return;
137237623b0SKonstantin Belousov 	p1 = p->p_reaper;
138237623b0SKonstantin Belousov 	LIST_FOREACH_SAFE(p2, &p->p_reaplist, p_reapsibling, ptmp) {
139237623b0SKonstantin Belousov 		LIST_REMOVE(p2, p_reapsibling);
140237623b0SKonstantin Belousov 		p2->p_reaper = p1;
141237623b0SKonstantin Belousov 		p2->p_reapsubtree = p->p_reapsubtree;
142237623b0SKonstantin Belousov 		LIST_INSERT_HEAD(&p1->p_reaplist, p2, p_reapsibling);
143237623b0SKonstantin Belousov 		if (exiting && p2->p_pptr == p) {
144237623b0SKonstantin Belousov 			PROC_LOCK(p2);
145237623b0SKonstantin Belousov 			proc_reparent(p2, p1);
146237623b0SKonstantin Belousov 			PROC_UNLOCK(p2);
147237623b0SKonstantin Belousov 		}
148237623b0SKonstantin Belousov 	}
149237623b0SKonstantin Belousov 	KASSERT(LIST_EMPTY(&p->p_reaplist), ("p_reaplist not empty"));
150237623b0SKonstantin Belousov 	p->p_treeflag &= ~P_TREE_REAPER;
151237623b0SKonstantin Belousov }
152237623b0SKonstantin Belousov 
1532e39e24fSKonstantin Belousov static void
1542e39e24fSKonstantin Belousov clear_orphan(struct proc *p)
1552e39e24fSKonstantin Belousov {
156d7359980SKonstantin Belousov 	struct proc *p1;
1572e39e24fSKonstantin Belousov 
158d7359980SKonstantin Belousov 	sx_assert(&proctree_lock, SA_XLOCKED);
159d7359980SKonstantin Belousov 	if ((p->p_treeflag & P_TREE_ORPHANED) == 0)
160d7359980SKonstantin Belousov 		return;
161d7359980SKonstantin Belousov 	if ((p->p_treeflag & P_TREE_FIRST_ORPHAN) != 0) {
162d7359980SKonstantin Belousov 		p1 = LIST_NEXT(p, p_orphan);
163d7359980SKonstantin Belousov 		if (p1 != NULL)
164d7359980SKonstantin Belousov 			p1->p_treeflag |= P_TREE_FIRST_ORPHAN;
165d7359980SKonstantin Belousov 		p->p_treeflag &= ~P_TREE_FIRST_ORPHAN;
1662e39e24fSKonstantin Belousov 	}
167d7359980SKonstantin Belousov 	LIST_REMOVE(p, p_orphan);
168d7359980SKonstantin Belousov 	p->p_treeflag &= ~P_TREE_ORPHANED;
1692e39e24fSKonstantin Belousov }
1702e39e24fSKonstantin Belousov 
171df8bae1dSRodney W. Grimes /*
172873fbcd7SRobert Watson  * exit -- death of process.
173df8bae1dSRodney W. Grimes  */
174fc0b1dbfSBruce Evans void
1758451d0ddSKip Macy sys_sys_exit(struct thread *td, struct sys_exit_args *uap)
176df8bae1dSRodney W. Grimes {
177b40ce416SJulian Elischer 
178b4490c6eSKonstantin Belousov 	exit1(td, uap->rval, 0);
179df8bae1dSRodney W. Grimes 	/* NOTREACHED */
180df8bae1dSRodney W. Grimes }
181df8bae1dSRodney W. Grimes 
182df8bae1dSRodney W. Grimes /*
183873fbcd7SRobert Watson  * Exit: deallocate address space and other resources, change proc state to
184873fbcd7SRobert Watson  * zombie, and unlink proc from allproc and parent's lists.  Save exit status
185873fbcd7SRobert Watson  * and rusage for wait().  Check for child processes and orphan them.
186df8bae1dSRodney W. Grimes  */
187fc0b1dbfSBruce Evans void
188b4490c6eSKonstantin Belousov exit1(struct thread *td, int rval, int signo)
189df8bae1dSRodney W. Grimes {
190a661bebeSMateusz Guzik 	struct proc *p, *nq, *q, *t;
191a661bebeSMateusz Guzik 	struct thread *tdt;
192df8bae1dSRodney W. Grimes 
193e17660e7SKris Kennaway 	mtx_assert(&Giant, MA_NOTOWNED);
194b4490c6eSKonstantin Belousov 	KASSERT(rval == 0 || signo == 0, ("exit1 rv %d sig %d", rval, signo));
1950cddd8f0SMatthew Dillon 
196276c5169SJohn Baldwin 	p = td->td_proc;
1975486ffc8SMarius Strobl 	/*
1985486ffc8SMarius Strobl 	 * XXX in case we're rebooting we just let init die in order to
1995486ffc8SMarius Strobl 	 * work around an unsolved stack overflow seen very late during
2005486ffc8SMarius Strobl 	 * shutdown on sparc64 when the gmirror worker process exists.
2015486ffc8SMarius Strobl 	 */
2025486ffc8SMarius Strobl 	if (p == initproc && rebooting == 0) {
203b4490c6eSKonstantin Belousov 		printf("init died (signal %d, exit %d)\n", signo, rval);
2045f7bd355SPoul-Henning Kamp 		panic("Going nowhere without my init!");
2055f7bd355SPoul-Henning Kamp 	}
2062c1011f7SJohn Dyson 
2077a6b989bSJohn Baldwin 	/*
2081bc93bb7SKonstantin Belousov 	 * Deref SU mp, since the thread does not return to userspace.
2091bc93bb7SKonstantin Belousov 	 */
2101bc93bb7SKonstantin Belousov 	if (softdep_ast_cleanup != NULL)
2111bc93bb7SKonstantin Belousov 		softdep_ast_cleanup();
2121bc93bb7SKonstantin Belousov 
2131bc93bb7SKonstantin Belousov 	/*
2142c10d16aSJeff Roberson 	 * MUST abort all other threads before proceeding past here.
2157a6b989bSJohn Baldwin 	 */
216e602ba25SJulian Elischer 	PROC_LOCK(p);
217e602ba25SJulian Elischer 	/*
218aba1ca52SKonstantin Belousov 	 * First check if some other thread or external request got
219aba1ca52SKonstantin Belousov 	 * here before us.  If so, act appropriately: exit or suspend.
220aba1ca52SKonstantin Belousov 	 * We must ensure that stop requests are handled before we set
221aba1ca52SKonstantin Belousov 	 * P_WEXIT.
222e602ba25SJulian Elischer 	 */
223e602ba25SJulian Elischer 	thread_suspend_check(0);
224aba1ca52SKonstantin Belousov 	while (p->p_flag & P_HADTHREADS) {
225e602ba25SJulian Elischer 		/*
226e602ba25SJulian Elischer 		 * Kill off the other threads. This requires
2276111dcd2SJohn Baldwin 		 * some co-operation from other parts of the kernel
2286111dcd2SJohn Baldwin 		 * so it may not be instantaneous.  With this state set
2296111dcd2SJohn Baldwin 		 * any thread entering the kernel from userspace will
230e602ba25SJulian Elischer 		 * thread_exit() in trap().  Any thread attempting to
2316111dcd2SJohn Baldwin 		 * sleep will return immediately with EINTR or EWOULDBLOCK
2326111dcd2SJohn Baldwin 		 * which will hopefully force them to back out to userland
2336111dcd2SJohn Baldwin 		 * freeing resources as they go.  Any thread attempting
234b3248998SJulian Elischer 		 * to return to userland will thread_exit() from userret().
2356111dcd2SJohn Baldwin 		 * thread_exit() will unsuspend us when the last of the
2366111dcd2SJohn Baldwin 		 * other threads exits.
237b370279eSDavid Xu 		 * If there is already a thread singler after resumption,
2386111dcd2SJohn Baldwin 		 * calling thread_single will fail; in that case, we just
239b370279eSDavid Xu 		 * re-check all suspension request, the thread should
240b370279eSDavid Xu 		 * either be suspended there or exit.
241e602ba25SJulian Elischer 		 */
2426ddcc233SKonstantin Belousov 		if (!thread_single(p, SINGLE_EXIT))
243e602ba25SJulian Elischer 			/*
244aba1ca52SKonstantin Belousov 			 * All other activity in this process is now
245aba1ca52SKonstantin Belousov 			 * stopped.  Threading support has been turned
246aba1ca52SKonstantin Belousov 			 * off.
247e602ba25SJulian Elischer 			 */
248aba1ca52SKonstantin Belousov 			break;
249aba1ca52SKonstantin Belousov 		/*
250aba1ca52SKonstantin Belousov 		 * Recheck for new stop or suspend requests which
251aba1ca52SKonstantin Belousov 		 * might appear while process lock was dropped in
252aba1ca52SKonstantin Belousov 		 * thread_single().
253aba1ca52SKonstantin Belousov 		 */
254aba1ca52SKonstantin Belousov 		thread_suspend_check(0);
255e602ba25SJulian Elischer 	}
2561c4bcd05SJeff Roberson 	KASSERT(p->p_numthreads == 1,
2571c4bcd05SJeff Roberson 	    ("exit1: proc %p exiting with %d threads", p, p->p_numthreads));
25858c77a9dSEdward Tomasz Napierala 	racct_sub(p, RACCT_NTHR, 1);
259b4490c6eSKonstantin Belousov 
260b4490c6eSKonstantin Belousov 	/* Let event handler change exit status */
261b4490c6eSKonstantin Belousov 	p->p_xexit = rval;
262b4490c6eSKonstantin Belousov 	p->p_xsig = signo;
263b4490c6eSKonstantin Belousov 
26406ad42b2SJohn Baldwin 	/*
26506ad42b2SJohn Baldwin 	 * Wakeup anyone in procfs' PIOCWAIT.  They should have a hold
26606ad42b2SJohn Baldwin 	 * on our vmspace, so we should block below until they have
26706ad42b2SJohn Baldwin 	 * released their reference to us.  Note that if they have
26806ad42b2SJohn Baldwin 	 * requested S_EXIT stops we will block here until they ack
26906ad42b2SJohn Baldwin 	 * via PIOCCONT.
27006ad42b2SJohn Baldwin 	 */
271b4490c6eSKonstantin Belousov 	_STOPEVENT(p, S_EXIT, 0);
27206ad42b2SJohn Baldwin 
27306ad42b2SJohn Baldwin 	/*
2740f14f15bSJohn Baldwin 	 * Ignore any pending request to stop due to a stop signal.
2750f14f15bSJohn Baldwin 	 * Once P_WEXIT is set, future requests will be ignored as
2760f14f15bSJohn Baldwin 	 * well.
2770f14f15bSJohn Baldwin 	 */
2780f14f15bSJohn Baldwin 	p->p_flag &= ~P_STOPPED_SIG;
2790f14f15bSJohn Baldwin 	KASSERT(!P_SHOULDSTOP(p), ("exiting process is stopped"));
2800f14f15bSJohn Baldwin 
2810f14f15bSJohn Baldwin 	/*
28206ad42b2SJohn Baldwin 	 * Note that we are exiting and do another wakeup of anyone in
28306ad42b2SJohn Baldwin 	 * PIOCWAIT in case they aren't listening for S_EXIT stops or
28406ad42b2SJohn Baldwin 	 * decided to wait again after we told them we are exiting.
28506ad42b2SJohn Baldwin 	 */
286e602ba25SJulian Elischer 	p->p_flag |= P_WEXIT;
28706ad42b2SJohn Baldwin 	wakeup(&p->p_stype);
28806ad42b2SJohn Baldwin 
28906ad42b2SJohn Baldwin 	/*
29006ad42b2SJohn Baldwin 	 * Wait for any processes that have a hold on our vmspace to
29106ad42b2SJohn Baldwin 	 * release their reference.
29206ad42b2SJohn Baldwin 	 */
29306ad42b2SJohn Baldwin 	while (p->p_lock > 0)
29406ad42b2SJohn Baldwin 		msleep(&p->p_lock, &p->p_mtx, PWAIT, "exithold", 0);
295ebceaf6dSDavid Xu 
296e602ba25SJulian Elischer 	PROC_UNLOCK(p);
2971c4bcd05SJeff Roberson 	/* Drain the limit callout while we don't have the proc locked */
2981c4bcd05SJeff Roberson 	callout_drain(&p->p_limco);
299b40ce416SJulian Elischer 
30000c28d96SRobert Watson #ifdef AUDIT
30100c28d96SRobert Watson 	/*
30200c28d96SRobert Watson 	 * The Sun BSM exit token contains two components: an exit status as
30300c28d96SRobert Watson 	 * passed to exit(), and a return value to indicate what sort of exit
30400c28d96SRobert Watson 	 * it was.  The exit status is WEXITSTATUS(rv), but it's not clear
30500c28d96SRobert Watson 	 * what the return value is.
30600c28d96SRobert Watson 	 */
307b4490c6eSKonstantin Belousov 	AUDIT_ARG_EXIT(rval, 0);
30800c28d96SRobert Watson 	AUDIT_SYSCALL_EXIT(0, td);
30900c28d96SRobert Watson #endif
31000c28d96SRobert Watson 
311bad2520aSMateusz Guzik 	/* Are we a task leader with peers? */
312bad2520aSMateusz Guzik 	if (p->p_peers != NULL && p == p->p_leader) {
313c6544064SJohn Baldwin 		mtx_lock(&ppeers_lock);
3142c1011f7SJohn Dyson 		q = p->p_peers;
315776e0b36SJohn Baldwin 		while (q != NULL) {
316776e0b36SJohn Baldwin 			PROC_LOCK(q);
3178451d0ddSKip Macy 			kern_psignal(q, SIGKILL);
318776e0b36SJohn Baldwin 			PROC_UNLOCK(q);
3192c1011f7SJohn Dyson 			q = q->p_peers;
3202c1011f7SJohn Dyson 		}
321c6544064SJohn Baldwin 		while (p->p_peers != NULL)
322c6544064SJohn Baldwin 			msleep(p, &ppeers_lock, PWAIT, "exit1", 0);
323c6544064SJohn Baldwin 		mtx_unlock(&ppeers_lock);
3242c1011f7SJohn Dyson 	}
3252c1011f7SJohn Dyson 
326fed06968SJulian Elischer 	/*
327e9189611SPeter Wemm 	 * Check if any loadable modules need anything done at process exit.
328b4490c6eSKonstantin Belousov 	 * E.g. SYSV IPC stuff.
329b4490c6eSKonstantin Belousov 	 * Event handler could change exit status.
330fed06968SJulian Elischer 	 * XXX what if one of these generates an error?
331fed06968SJulian Elischer 	 */
33275b8b3b2SJohn Baldwin 	EVENTHANDLER_INVOKE(process_exit, p);
333a914fb6bSJohn Baldwin 
334df8bae1dSRodney W. Grimes 	/*
335df8bae1dSRodney W. Grimes 	 * If parent is waiting for us to exit or exec,
336df8bae1dSRodney W. Grimes 	 * P_PPWAIT is set; we will wakeup the parent below.
337df8bae1dSRodney W. Grimes 	 */
338a914fb6bSJohn Baldwin 	PROC_LOCK(p);
339a282253aSJulian Elischer 	stopprofclock(p);
340888d4d4fSKonstantin Belousov 	p->p_flag &= ~(P_TRACED | P_PPWAIT | P_PPTRACE);
3418d570f64SJohn Baldwin 	p->p_ptevents = 0;
3425499ea01SJohn Baldwin 
3435499ea01SJohn Baldwin 	/*
3445499ea01SJohn Baldwin 	 * Stop the real interval timer.  If the handler is currently
3455499ea01SJohn Baldwin 	 * executing, prevent it from rearming itself and let it finish.
3465499ea01SJohn Baldwin 	 */
3475499ea01SJohn Baldwin 	if (timevalisset(&p->p_realtimer.it_value) &&
34856d48d6dSKonstantin Belousov 	    _callout_stop_safe(&p->p_itcallout, CS_EXECUTING, NULL) == 0) {
3495499ea01SJohn Baldwin 		timevalclear(&p->p_realtimer.it_interval);
3505499ea01SJohn Baldwin 		msleep(&p->p_itcallout, &p->p_mtx, PWAIT, "ritwait", 0);
3515499ea01SJohn Baldwin 		KASSERT(!timevalisset(&p->p_realtimer.it_value),
3525499ea01SJohn Baldwin 		    ("realtime timer is still armed"));
3535499ea01SJohn Baldwin 	}
3542a339d9eSKonstantin Belousov 
35596d7f8efSTim J. Robbins 	PROC_UNLOCK(p);
356df8bae1dSRodney W. Grimes 
3572a339d9eSKonstantin Belousov 	umtx_thread_exit(td);
3582a339d9eSKonstantin Belousov 
359df8bae1dSRodney W. Grimes 	/*
360831d27a9SDon Lewis 	 * Reset any sigio structures pointing to us as a result of
361831d27a9SDon Lewis 	 * F_SETOWN with our pid.
362831d27a9SDon Lewis 	 */
363831d27a9SDon Lewis 	funsetownlst(&p->p_sigiolst);
364831d27a9SDon Lewis 
365831d27a9SDon Lewis 	/*
366c0bc2867SGleb Smirnoff 	 * If this process has an nlminfo data area (for lockd), release it
367c0bc2867SGleb Smirnoff 	 */
368c0bc2867SGleb Smirnoff 	if (nlminfo_release_p != NULL && p->p_nlminfo != NULL)
369c0bc2867SGleb Smirnoff 		(*nlminfo_release_p)(p);
370c0bc2867SGleb Smirnoff 
371c0bc2867SGleb Smirnoff 	/*
372df8bae1dSRodney W. Grimes 	 * Close open files and release open-file table.
373df8bae1dSRodney W. Grimes 	 * This may block!
374df8bae1dSRodney W. Grimes 	 */
3752609222aSPawel Jakub Dawidek 	fdescfree(td);
376df8bae1dSRodney W. Grimes 
377a914fb6bSJohn Baldwin 	/*
378a2587073SPoul-Henning Kamp 	 * If this thread tickled GEOM, we need to wait for the giggling to
379a2587073SPoul-Henning Kamp 	 * stop before we return to userland
380a2587073SPoul-Henning Kamp 	 */
381a2587073SPoul-Henning Kamp 	if (td->td_pflags & TDP_GEOM)
382a2587073SPoul-Henning Kamp 		g_waitidle();
383a2587073SPoul-Henning Kamp 
384a2587073SPoul-Henning Kamp 	/*
385a914fb6bSJohn Baldwin 	 * Remove ourself from our leader's peer list and wake our leader.
386a914fb6bSJohn Baldwin 	 */
387bad2520aSMateusz Guzik 	if (p->p_leader->p_peers != NULL) {
388c6544064SJohn Baldwin 		mtx_lock(&ppeers_lock);
389bad2520aSMateusz Guzik 		if (p->p_leader->p_peers != NULL) {
39079fc0bf4SMike Smith 			q = p->p_leader;
39179fc0bf4SMike Smith 			while (q->p_peers != p)
39279fc0bf4SMike Smith 				q = q->p_peers;
39379fc0bf4SMike Smith 			q->p_peers = p->p_peers;
3947f05b035SAlfred Perlstein 			wakeup(p->p_leader);
39579fc0bf4SMike Smith 		}
396c6544064SJohn Baldwin 		mtx_unlock(&ppeers_lock);
397bad2520aSMateusz Guzik 	}
39879fc0bf4SMike Smith 
39957051fdcSTor Egge 	vmspace_exit(td);
40017182b13SMateusz Guzik 	killjobc();
401b40ce416SJulian Elischer 	(void)acct_process(td);
402bc093719SEd Schouten 
403df8bae1dSRodney W. Grimes #ifdef KTRACE
4042c255e9dSRobert Watson 	ktrprocexit(td);
405df8bae1dSRodney W. Grimes #endif
406df8bae1dSRodney W. Grimes 	/*
407ee42d0a9SDavid Malone 	 * Release reference to text vnode
408ee42d0a9SDavid Malone 	 */
40988f98985SMateusz Guzik 	if (p->p_textvp != NULL) {
41088f98985SMateusz Guzik 		vrele(p->p_textvp);
411ee42d0a9SDavid Malone 		p->p_textvp = NULL;
412ee42d0a9SDavid Malone 	}
413ee42d0a9SDavid Malone 
414ee42d0a9SDavid Malone 	/*
415d7aadbf9SJohn Baldwin 	 * Release our limits structure.
416d7aadbf9SJohn Baldwin 	 */
41788f98985SMateusz Guzik 	lim_free(p->p_limit);
418d7aadbf9SJohn Baldwin 	p->p_limit = NULL;
419d7aadbf9SJohn Baldwin 
420cf7d9a8cSDavid Xu 	tidhash_remove(td);
421cf7d9a8cSDavid Xu 
422d7aadbf9SJohn Baldwin 	/*
423df8bae1dSRodney W. Grimes 	 * Remove proc from allproc queue and pidhash chain.
424df8bae1dSRodney W. Grimes 	 * Place onto zombproc.  Unlink from parent's child list.
425df8bae1dSRodney W. Grimes 	 */
4261005a129SJohn Baldwin 	sx_xlock(&allproc_lock);
427b75356e1SJeffrey Hsu 	LIST_REMOVE(p, p_list);
428b75356e1SJeffrey Hsu 	LIST_INSERT_HEAD(&zombproc, p, p_list);
429b75356e1SJeffrey Hsu 	LIST_REMOVE(p, p_hash);
4301005a129SJohn Baldwin 	sx_xunlock(&allproc_lock);
431df8bae1dSRodney W. Grimes 
43237f84a60SJohn Baldwin 	/*
4331bba2a94SJohn Baldwin 	 * Call machine-dependent code to release any
4341bba2a94SJohn Baldwin 	 * machine-dependent resources other than the address space.
4351bba2a94SJohn Baldwin 	 * The address space is released by "vmspace_exitfree(p)" in
4361bba2a94SJohn Baldwin 	 * vm_waitproc().
4371bba2a94SJohn Baldwin 	 */
4381bba2a94SJohn Baldwin 	cpu_exit(td);
4391bba2a94SJohn Baldwin 
4401bba2a94SJohn Baldwin 	WITNESS_WARN(WARN_PANIC, NULL, "process (pid %d) exiting", p->p_pid);
4411bba2a94SJohn Baldwin 
4421bba2a94SJohn Baldwin 	/*
443a661bebeSMateusz Guzik 	 * Reparent all children processes:
444a661bebeSMateusz Guzik 	 * - traced ones to the original parent (or init if we are that parent)
445a661bebeSMateusz Guzik 	 * - the rest to init
44637f84a60SJohn Baldwin 	 */
4471005a129SJohn Baldwin 	sx_xlock(&proctree_lock);
4482e3c8fcbSPoul-Henning Kamp 	q = LIST_FIRST(&p->p_children);
449a914fb6bSJohn Baldwin 	if (q != NULL)		/* only need this if any child is S_ZOMB */
450237623b0SKonstantin Belousov 		wakeup(q->p_reaper);
451a914fb6bSJohn Baldwin 	for (; q != NULL; q = nq) {
4522e3c8fcbSPoul-Henning Kamp 		nq = LIST_NEXT(q, p_sibling);
453a914fb6bSJohn Baldwin 		PROC_LOCK(q);
4544ac9ae70SJulian Elischer 		q->p_sigparent = SIGCHLD;
455904c5ec4SDavid Xu 
456a661bebeSMateusz Guzik 		if (!(q->p_flag & P_TRACED)) {
457237623b0SKonstantin Belousov 			proc_reparent(q, q->p_reaper);
458a661bebeSMateusz Guzik 		} else {
459a661bebeSMateusz Guzik 			/*
460a661bebeSMateusz Guzik 			 * Traced processes are killed since their existence
461a661bebeSMateusz Guzik 			 * means someone is screwing up.
462a661bebeSMateusz Guzik 			 */
463a661bebeSMateusz Guzik 			t = proc_realparent(q);
464a661bebeSMateusz Guzik 			if (t == p) {
465237623b0SKonstantin Belousov 				proc_reparent(q, q->p_reaper);
466a661bebeSMateusz Guzik 			} else {
467a661bebeSMateusz Guzik 				PROC_LOCK(t);
468a661bebeSMateusz Guzik 				proc_reparent(q, t);
469a661bebeSMateusz Guzik 				PROC_UNLOCK(t);
470a661bebeSMateusz Guzik 			}
4715085ecb7SKonstantin Belousov 			/*
4725085ecb7SKonstantin Belousov 			 * Since q was found on our children list, the
4735085ecb7SKonstantin Belousov 			 * proc_reparent() call moved q to the orphan
4745085ecb7SKonstantin Belousov 			 * list due to present P_TRACED flag. Clear
4755085ecb7SKonstantin Belousov 			 * orphan link for q now while q is locked.
4765085ecb7SKonstantin Belousov 			 */
4775085ecb7SKonstantin Belousov 			clear_orphan(q);
478c2836532SDavid Xu 			q->p_flag &= ~(P_TRACED | P_STOPPED_TRACE);
479b7a25e63SKonstantin Belousov 			q->p_flag2 &= ~P2_PTRACE_FSTP;
4808d570f64SJohn Baldwin 			q->p_ptevents = 0;
481b7a25e63SKonstantin Belousov 			FOREACH_THREAD_IN_PROC(q, tdt) {
482b7a25e63SKonstantin Belousov 				tdt->td_dbgflags &= ~(TDB_SUSPEND | TDB_XSIG |
483b7a25e63SKonstantin Belousov 				    TDB_FSTP);
484b7a25e63SKonstantin Belousov 			}
4858451d0ddSKip Macy 			kern_psignal(q, SIGKILL);
486c65437a3SJohn Baldwin 		}
487a914fb6bSJohn Baldwin 		PROC_UNLOCK(q);
488df8bae1dSRodney W. Grimes 	}
489df8bae1dSRodney W. Grimes 
4905085ecb7SKonstantin Belousov 	/*
4915085ecb7SKonstantin Belousov 	 * Also get rid of our orphans.
4925085ecb7SKonstantin Belousov 	 */
4935085ecb7SKonstantin Belousov 	while ((q = LIST_FIRST(&p->p_orphans)) != NULL) {
4945085ecb7SKonstantin Belousov 		PROC_LOCK(q);
495515b7a0bSJohn Baldwin 		CTR2(KTR_PTRACE, "exit: pid %d, clearing orphan %d", p->p_pid,
496515b7a0bSJohn Baldwin 		    q->p_pid);
4975085ecb7SKonstantin Belousov 		clear_orphan(q);
4985085ecb7SKonstantin Belousov 		PROC_UNLOCK(q);
4995085ecb7SKonstantin Belousov 	}
5005085ecb7SKonstantin Belousov 
5011c4bcd05SJeff Roberson 	/* Save exit status. */
502d7aadbf9SJohn Baldwin 	PROC_LOCK(p);
503cbf4e354SDavid Xu 	p->p_xthread = td;
5045d217f17SJohn Birrell 
5050304c731SJamie Gritton 	/* Tell the prison that we are gone. */
506413628a7SBjoern A. Zeeb 	prison_proc_free(p->p_ucred->cr_prison);
507413628a7SBjoern A. Zeeb 
5085d217f17SJohn Birrell #ifdef KDTRACE_HOOKS
5095d217f17SJohn Birrell 	/*
5105d217f17SJohn Birrell 	 * Tell the DTrace fasttrap provider about the exit if it
5115d217f17SJohn Birrell 	 * has declared an interest.
5125d217f17SJohn Birrell 	 */
5135d217f17SJohn Birrell 	if (dtrace_fasttrap_exit)
5145d217f17SJohn Birrell 		dtrace_fasttrap_exit(p);
5155d217f17SJohn Birrell #endif
5165d217f17SJohn Birrell 
5171c4bcd05SJeff Roberson 	/*
5187a6b989bSJohn Baldwin 	 * Notify interested parties of our demise.
519cb679c38SJonathan Lemon 	 */
5209e590ff0SKonstantin Belousov 	KNOTE_LOCKED(p->p_klist, NOTE_EXIT);
5217eaec467SJohn Baldwin 
5225d217f17SJohn Birrell #ifdef KDTRACE_HOOKS
5235d217f17SJohn Birrell 	int reason = CLD_EXITED;
524b4490c6eSKonstantin Belousov 	if (WCOREDUMP(signo))
5255d217f17SJohn Birrell 		reason = CLD_DUMPED;
526b4490c6eSKonstantin Belousov 	else if (WIFSIGNALED(signo))
5275d217f17SJohn Birrell 		reason = CLD_KILLED;
52836160958SMark Johnston 	SDT_PROBE1(proc, , , exit, reason);
5295d217f17SJohn Birrell #endif
5305d217f17SJohn Birrell 
5311a29c806SOlivier Houchard 	/*
532cfb5f768SJonathan Anderson 	 * If this is a process with a descriptor, we may not need to deliver
533cfb5f768SJonathan Anderson 	 * a signal to the parent.  proctree_lock is held over
534cfb5f768SJonathan Anderson 	 * procdesc_exit() to serialize concurrent calls to close() and
535cfb5f768SJonathan Anderson 	 * exit().
536cfb5f768SJonathan Anderson 	 */
537cfb5f768SJonathan Anderson 	if (p->p_procdesc == NULL || procdesc_exit(p)) {
538cfb5f768SJonathan Anderson 		/*
539cfb5f768SJonathan Anderson 		 * Notify parent that we're gone.  If parent has the
540cfb5f768SJonathan Anderson 		 * PS_NOCLDWAIT flag set, or if the handler is set to SIG_IGN,
541cfb5f768SJonathan Anderson 		 * notify process 1 instead (and hope it will handle this
542cfb5f768SJonathan Anderson 		 * situation).
543df8bae1dSRodney W. Grimes 		 */
544d7aadbf9SJohn Baldwin 		PROC_LOCK(p->p_pptr);
54590af4afaSJohn Baldwin 		mtx_lock(&p->p_pptr->p_sigacts->ps_mtx);
546cfb5f768SJonathan Anderson 		if (p->p_pptr->p_sigacts->ps_flag &
547cfb5f768SJonathan Anderson 		    (PS_NOCLDWAIT | PS_CLDSIGIGN)) {
548276c5169SJohn Baldwin 			struct proc *pp;
549276c5169SJohn Baldwin 
55090af4afaSJohn Baldwin 			mtx_unlock(&p->p_pptr->p_sigacts->ps_mtx);
551276c5169SJohn Baldwin 			pp = p->p_pptr;
552f591779bSSeigo Tanimura 			PROC_UNLOCK(pp);
553237623b0SKonstantin Belousov 			proc_reparent(p, p->p_reaper);
55455b5f2a2SDon Lewis 			p->p_sigparent = SIGCHLD;
555f591779bSSeigo Tanimura 			PROC_LOCK(p->p_pptr);
556007abb3dSKonstantin Belousov 
557245f17d4SJoerg Wunsch 			/*
558007abb3dSKonstantin Belousov 			 * Notify parent, so in case he was wait(2)ing or
5596fae832aSKonstantin Belousov 			 * executing waitpid(2) with our pid, he will
560245f17d4SJoerg Wunsch 			 * continue.
561245f17d4SJoerg Wunsch 			 */
5627f05b035SAlfred Perlstein 			wakeup(pp);
56390af4afaSJohn Baldwin 		} else
56490af4afaSJohn Baldwin 			mtx_unlock(&p->p_pptr->p_sigacts->ps_mtx);
565245f17d4SJoerg Wunsch 
566237623b0SKonstantin Belousov 		if (p->p_pptr == p->p_reaper || p->p_pptr == initproc)
567237623b0SKonstantin Belousov 			childproc_exited(p);
568ebceaf6dSDavid Xu 		else if (p->p_sigparent != 0) {
569ebceaf6dSDavid Xu 			if (p->p_sigparent == SIGCHLD)
570ebceaf6dSDavid Xu 				childproc_exited(p);
571ebceaf6dSDavid Xu 			else	/* LINUX thread */
5728451d0ddSKip Macy 				kern_psignal(p->p_pptr, p->p_sigparent);
573ebceaf6dSDavid Xu 		}
574cfb5f768SJonathan Anderson 	} else
575cfb5f768SJonathan Anderson 		PROC_LOCK(p->p_pptr);
576d7aadbf9SJohn Baldwin 	sx_xunlock(&proctree_lock);
577696058c3SJulian Elischer 
578eb30c1c0SPeter Wemm 	/*
579f71e748dSDavid Xu 	 * The state PRS_ZOMBIE prevents other proesses from sending
580f71e748dSDavid Xu 	 * signal to the process, to avoid memory leak, we free memory
581f71e748dSDavid Xu 	 * for signal queue at the time when the state is set.
582f71e748dSDavid Xu 	 */
583f71e748dSDavid Xu 	sigqueue_flush(&p->p_sigqueue);
584f71e748dSDavid Xu 	sigqueue_flush(&td->td_sigqueue);
585f71e748dSDavid Xu 
586f71e748dSDavid Xu 	/*
587462f31bfSJohn Baldwin 	 * We have to wait until after acquiring all locks before
588a9a64385SJohn Baldwin 	 * changing p_state.  We need to avoid all possible context
589a9a64385SJohn Baldwin 	 * switches (including ones from blocking on a mutex) while
590ddf9c4f7SJohn Baldwin 	 * marked as a zombie.  We also have to set the zombie state
591ddf9c4f7SJohn Baldwin 	 * before we release the parent process' proc lock to avoid
592ddf9c4f7SJohn Baldwin 	 * a lost wakeup.  So, we first call wakeup, then we grab the
593ddf9c4f7SJohn Baldwin 	 * sched lock, update the state, and release the parent process'
594ddf9c4f7SJohn Baldwin 	 * proc lock.
595eb30c1c0SPeter Wemm 	 */
596ddf9c4f7SJohn Baldwin 	wakeup(p->p_pptr);
597aeb32571SKonstantin Belousov 	cv_broadcast(&p->p_pwait);
598982d11f8SJeff Roberson 	sched_exit(p->p_pptr, td);
599982d11f8SJeff Roberson 	PROC_SLOCK(p);
600e602ba25SJulian Elischer 	p->p_state = PRS_ZOMBIE;
601d7aadbf9SJohn Baldwin 	PROC_UNLOCK(p->p_pptr);
602871684b8SBruce Evans 
603f6f230feSJeff Roberson 	/*
604a140976eSAttilio Rao 	 * Save our children's rusage information in our exit rusage.
605a140976eSAttilio Rao 	 */
6065c7bebf9SKonstantin Belousov 	PROC_STATLOCK(p);
607a140976eSAttilio Rao 	ruadd(&p->p_ru, &p->p_rux, &p->p_stats->p_cru, &p->p_crux);
6085c7bebf9SKonstantin Belousov 	PROC_STATUNLOCK(p);
609a140976eSAttilio Rao 
610a140976eSAttilio Rao 	/*
611696058c3SJulian Elischer 	 * Make sure the scheduler takes this thread out of its tables etc.
612e602ba25SJulian Elischer 	 * This will also release this thread's reference to the ucred.
613696058c3SJulian Elischer 	 * Other thread parts to release include pcb bits and such.
614e602ba25SJulian Elischer 	 */
615e602ba25SJulian Elischer 	thread_exit();
616df8bae1dSRodney W. Grimes }
617df8bae1dSRodney W. Grimes 
61825f6e35aSPoul-Henning Kamp 
61925f6e35aSPoul-Henning Kamp #ifndef _SYS_SYSPROTO_H_
62025f6e35aSPoul-Henning Kamp struct abort2_args {
62125f6e35aSPoul-Henning Kamp 	char *why;
62225f6e35aSPoul-Henning Kamp 	int nargs;
62325f6e35aSPoul-Henning Kamp 	void **args;
62425f6e35aSPoul-Henning Kamp };
62525f6e35aSPoul-Henning Kamp #endif
62625f6e35aSPoul-Henning Kamp 
62725f6e35aSPoul-Henning Kamp int
6288451d0ddSKip Macy sys_abort2(struct thread *td, struct abort2_args *uap)
62925f6e35aSPoul-Henning Kamp {
63025f6e35aSPoul-Henning Kamp 	struct proc *p = td->td_proc;
63125f6e35aSPoul-Henning Kamp 	struct sbuf *sb;
63225f6e35aSPoul-Henning Kamp 	void *uargs[16];
63325f6e35aSPoul-Henning Kamp 	int error, i, sig;
63425f6e35aSPoul-Henning Kamp 
63525f6e35aSPoul-Henning Kamp 	/*
63625f6e35aSPoul-Henning Kamp 	 * Do it right now so we can log either proper call of abort2(), or
63725f6e35aSPoul-Henning Kamp 	 * note, that invalid argument was passed. 512 is big enough to
63825f6e35aSPoul-Henning Kamp 	 * handle 16 arguments' descriptions with additional comments.
63925f6e35aSPoul-Henning Kamp 	 */
64025f6e35aSPoul-Henning Kamp 	sb = sbuf_new(NULL, NULL, 512, SBUF_FIXEDLEN);
64125f6e35aSPoul-Henning Kamp 	sbuf_clear(sb);
64225f6e35aSPoul-Henning Kamp 	sbuf_printf(sb, "%s(pid %d uid %d) aborted: ",
64325f6e35aSPoul-Henning Kamp 	    p->p_comm, p->p_pid, td->td_ucred->cr_uid);
64425f6e35aSPoul-Henning Kamp 	/*
64525f6e35aSPoul-Henning Kamp 	 * Since we can't return from abort2(), send SIGKILL in cases, where
64625f6e35aSPoul-Henning Kamp 	 * abort2() was called improperly
64725f6e35aSPoul-Henning Kamp 	 */
64825f6e35aSPoul-Henning Kamp 	sig = SIGKILL;
64925f6e35aSPoul-Henning Kamp 	/* Prevent from DoSes from user-space. */
65025f6e35aSPoul-Henning Kamp 	if (uap->nargs < 0 || uap->nargs > 16)
65125f6e35aSPoul-Henning Kamp 		goto out;
6524218a731SPoul-Henning Kamp 	if (uap->nargs > 0) {
65325f6e35aSPoul-Henning Kamp 		if (uap->args == NULL)
65425f6e35aSPoul-Henning Kamp 			goto out;
65525f6e35aSPoul-Henning Kamp 		error = copyin(uap->args, uargs, uap->nargs * sizeof(void *));
65625f6e35aSPoul-Henning Kamp 		if (error != 0)
65725f6e35aSPoul-Henning Kamp 			goto out;
6584218a731SPoul-Henning Kamp 	}
65925f6e35aSPoul-Henning Kamp 	/*
66025f6e35aSPoul-Henning Kamp 	 * Limit size of 'reason' string to 128. Will fit even when
66125f6e35aSPoul-Henning Kamp 	 * maximal number of arguments was chosen to be logged.
66225f6e35aSPoul-Henning Kamp 	 */
66325f6e35aSPoul-Henning Kamp 	if (uap->why != NULL) {
66425f6e35aSPoul-Henning Kamp 		error = sbuf_copyin(sb, uap->why, 128);
66525f6e35aSPoul-Henning Kamp 		if (error < 0)
66625f6e35aSPoul-Henning Kamp 			goto out;
66725f6e35aSPoul-Henning Kamp 	} else {
66825f6e35aSPoul-Henning Kamp 		sbuf_printf(sb, "(null)");
66925f6e35aSPoul-Henning Kamp 	}
6704218a731SPoul-Henning Kamp 	if (uap->nargs > 0) {
67125f6e35aSPoul-Henning Kamp 		sbuf_printf(sb, "(");
67225f6e35aSPoul-Henning Kamp 		for (i = 0;i < uap->nargs; i++)
67325f6e35aSPoul-Henning Kamp 			sbuf_printf(sb, "%s%p", i == 0 ? "" : ", ", uargs[i]);
67425f6e35aSPoul-Henning Kamp 		sbuf_printf(sb, ")");
67525f6e35aSPoul-Henning Kamp 	}
67625f6e35aSPoul-Henning Kamp 	/*
67725f6e35aSPoul-Henning Kamp 	 * Final stage: arguments were proper, string has been
67825f6e35aSPoul-Henning Kamp 	 * successfully copied from userspace, and copying pointers
67925f6e35aSPoul-Henning Kamp 	 * from user-space succeed.
68025f6e35aSPoul-Henning Kamp 	 */
68125f6e35aSPoul-Henning Kamp 	sig = SIGABRT;
68225f6e35aSPoul-Henning Kamp out:
68325f6e35aSPoul-Henning Kamp 	if (sig == SIGKILL) {
68425f6e35aSPoul-Henning Kamp 		sbuf_trim(sb);
68525f6e35aSPoul-Henning Kamp 		sbuf_printf(sb, " (Reason text inaccessible)");
68625f6e35aSPoul-Henning Kamp 	}
68725f6e35aSPoul-Henning Kamp 	sbuf_cat(sb, "\n");
68825f6e35aSPoul-Henning Kamp 	sbuf_finish(sb);
68925f6e35aSPoul-Henning Kamp 	log(LOG_INFO, "%s", sbuf_data(sb));
69025f6e35aSPoul-Henning Kamp 	sbuf_delete(sb);
691b4490c6eSKonstantin Belousov 	exit1(td, 0, sig);
69225f6e35aSPoul-Henning Kamp 	return (0);
69325f6e35aSPoul-Henning Kamp }
69425f6e35aSPoul-Henning Kamp 
69525f6e35aSPoul-Henning Kamp 
696b2f9e8b1SBruce Evans #ifdef COMPAT_43
697234216efSMatthew Dillon /*
698a9a64385SJohn Baldwin  * The dirty work is handled by kern_wait().
699234216efSMatthew Dillon  */
70026f9a767SRodney W. Grimes int
701830c3153SDag-Erling Smørgrav owait(struct thread *td, struct owait_args *uap __unused)
702df8bae1dSRodney W. Grimes {
703b7e23e82SJohn Baldwin 	int error, status;
704df8bae1dSRodney W. Grimes 
705b7e23e82SJohn Baldwin 	error = kern_wait(td, WAIT_ANY, &status, 0, NULL);
706b7e23e82SJohn Baldwin 	if (error == 0)
707b7e23e82SJohn Baldwin 		td->td_retval[1] = status;
708b7e23e82SJohn Baldwin 	return (error);
709df8bae1dSRodney W. Grimes }
710b2f9e8b1SBruce Evans #endif /* COMPAT_43 */
711df8bae1dSRodney W. Grimes 
712234216efSMatthew Dillon /*
713a9a64385SJohn Baldwin  * The dirty work is handled by kern_wait().
714234216efSMatthew Dillon  */
71526f9a767SRodney W. Grimes int
716f13b5a0fSKonstantin Belousov sys_wait4(struct thread *td, struct wait4_args *uap)
717df8bae1dSRodney W. Grimes {
71878c85e8dSJohn Baldwin 	struct rusage ru, *rup;
719b7e23e82SJohn Baldwin 	int error, status;
720b40ce416SJulian Elischer 
72178c85e8dSJohn Baldwin 	if (uap->rusage != NULL)
72278c85e8dSJohn Baldwin 		rup = &ru;
72378c85e8dSJohn Baldwin 	else
72478c85e8dSJohn Baldwin 		rup = NULL;
72578c85e8dSJohn Baldwin 	error = kern_wait(td, uap->pid, &status, uap->options, rup);
726d30e66e5SJilles Tjoelker 	if (uap->status != NULL && error == 0 && td->td_retval[0] != 0)
727b7e23e82SJohn Baldwin 		error = copyout(&status, uap->status, sizeof(status));
728d30e66e5SJilles Tjoelker 	if (uap->rusage != NULL && error == 0 && td->td_retval[0] != 0)
729b7e23e82SJohn Baldwin 		error = copyout(&ru, uap->rusage, sizeof(struct rusage));
730b7e23e82SJohn Baldwin 	return (error);
731df8bae1dSRodney W. Grimes }
732df8bae1dSRodney W. Grimes 
733f13b5a0fSKonstantin Belousov int
734f13b5a0fSKonstantin Belousov sys_wait6(struct thread *td, struct wait6_args *uap)
735f13b5a0fSKonstantin Belousov {
736f13b5a0fSKonstantin Belousov 	struct __wrusage wru, *wrup;
737f13b5a0fSKonstantin Belousov 	siginfo_t si, *sip;
738f13b5a0fSKonstantin Belousov 	idtype_t idtype;
739f13b5a0fSKonstantin Belousov 	id_t id;
740a2a85596SKonstantin Belousov 	int error, status;
741f13b5a0fSKonstantin Belousov 
742f13b5a0fSKonstantin Belousov 	idtype = uap->idtype;
743f13b5a0fSKonstantin Belousov 	id = uap->id;
744f13b5a0fSKonstantin Belousov 
745f13b5a0fSKonstantin Belousov 	if (uap->wrusage != NULL)
746f13b5a0fSKonstantin Belousov 		wrup = &wru;
747f13b5a0fSKonstantin Belousov 	else
748f13b5a0fSKonstantin Belousov 		wrup = NULL;
749f13b5a0fSKonstantin Belousov 
750f13b5a0fSKonstantin Belousov 	if (uap->info != NULL) {
751f13b5a0fSKonstantin Belousov 		sip = &si;
752f13b5a0fSKonstantin Belousov 		bzero(sip, sizeof(*sip));
753f13b5a0fSKonstantin Belousov 	} else
754f13b5a0fSKonstantin Belousov 		sip = NULL;
755f13b5a0fSKonstantin Belousov 
756f13b5a0fSKonstantin Belousov 	/*
757f13b5a0fSKonstantin Belousov 	 *  We expect all callers of wait6() to know about WEXITED and
758f13b5a0fSKonstantin Belousov 	 *  WTRAPPED.
759f13b5a0fSKonstantin Belousov 	 */
760f13b5a0fSKonstantin Belousov 	error = kern_wait6(td, idtype, id, &status, uap->options, wrup, sip);
761f13b5a0fSKonstantin Belousov 
762d30e66e5SJilles Tjoelker 	if (uap->status != NULL && error == 0 && td->td_retval[0] != 0)
763f13b5a0fSKonstantin Belousov 		error = copyout(&status, uap->status, sizeof(status));
764d30e66e5SJilles Tjoelker 	if (uap->wrusage != NULL && error == 0 && td->td_retval[0] != 0)
765f13b5a0fSKonstantin Belousov 		error = copyout(&wru, uap->wrusage, sizeof(wru));
766f13b5a0fSKonstantin Belousov 	if (uap->info != NULL && error == 0)
767f13b5a0fSKonstantin Belousov 		error = copyout(&si, uap->info, sizeof(si));
768f13b5a0fSKonstantin Belousov 	return (error);
769f13b5a0fSKonstantin Belousov }
770f13b5a0fSKonstantin Belousov 
771324fb6beSRobert Watson /*
772324fb6beSRobert Watson  * Reap the remains of a zombie process and optionally return status and
773324fb6beSRobert Watson  * rusage.  Asserts and will release both the proctree_lock and the process
774324fb6beSRobert Watson  * lock as part of its work.
775324fb6beSRobert Watson  */
776cfb5f768SJonathan Anderson void
777f13b5a0fSKonstantin Belousov proc_reap(struct thread *td, struct proc *p, int *status, int options)
778324fb6beSRobert Watson {
779324fb6beSRobert Watson 	struct proc *q, *t;
780324fb6beSRobert Watson 
781324fb6beSRobert Watson 	sx_assert(&proctree_lock, SA_XLOCKED);
782324fb6beSRobert Watson 	PROC_LOCK_ASSERT(p, MA_OWNED);
783324fb6beSRobert Watson 	PROC_SLOCK_ASSERT(p, MA_OWNED);
784324fb6beSRobert Watson 	KASSERT(p->p_state == PRS_ZOMBIE, ("proc_reap: !PRS_ZOMBIE"));
785324fb6beSRobert Watson 
786324fb6beSRobert Watson 	q = td->td_proc;
787f13b5a0fSKonstantin Belousov 
788324fb6beSRobert Watson 	PROC_SUNLOCK(p);
789324fb6beSRobert Watson 	if (status)
790b4490c6eSKonstantin Belousov 		*status = KW_EXITCODE(p->p_xexit, p->p_xsig);
791324fb6beSRobert Watson 	if (options & WNOWAIT) {
792324fb6beSRobert Watson 		/*
793324fb6beSRobert Watson 		 *  Only poll, returning the status.  Caller does not wish to
794324fb6beSRobert Watson 		 * release the proc struct just yet.
795324fb6beSRobert Watson 		 */
796324fb6beSRobert Watson 		PROC_UNLOCK(p);
797324fb6beSRobert Watson 		sx_xunlock(&proctree_lock);
798324fb6beSRobert Watson 		return;
799324fb6beSRobert Watson 	}
800324fb6beSRobert Watson 
801324fb6beSRobert Watson 	PROC_LOCK(q);
802324fb6beSRobert Watson 	sigqueue_take(p->p_ksi);
803324fb6beSRobert Watson 	PROC_UNLOCK(q);
804324fb6beSRobert Watson 
805324fb6beSRobert Watson 	/*
806324fb6beSRobert Watson 	 * If we got the child via a ptrace 'attach', we need to give it back
807324fb6beSRobert Watson 	 * to the old parent.
808324fb6beSRobert Watson 	 */
809c209e3e2SJohn Baldwin 	if (p->p_oppid != 0 && p->p_oppid != p->p_pptr->p_pid) {
810c209e3e2SJohn Baldwin 		PROC_UNLOCK(p);
811d7359980SKonstantin Belousov 		t = proc_realparent(p);
812d7359980SKonstantin Belousov 		PROC_LOCK(t);
813324fb6beSRobert Watson 		PROC_LOCK(p);
814515b7a0bSJohn Baldwin 		CTR2(KTR_PTRACE,
815515b7a0bSJohn Baldwin 		    "wait: traced child %d moved back to parent %d", p->p_pid,
816515b7a0bSJohn Baldwin 		    t->p_pid);
817324fb6beSRobert Watson 		proc_reparent(p, t);
818f528c3fdSDavid E. O'Brien 		p->p_oppid = 0;
819324fb6beSRobert Watson 		PROC_UNLOCK(p);
820ad6eec7bSJohn Baldwin 		pksignal(t, SIGCHLD, p->p_ksi);
821324fb6beSRobert Watson 		wakeup(t);
822324fb6beSRobert Watson 		cv_broadcast(&p->p_pwait);
823324fb6beSRobert Watson 		PROC_UNLOCK(t);
824324fb6beSRobert Watson 		sx_xunlock(&proctree_lock);
825324fb6beSRobert Watson 		return;
826324fb6beSRobert Watson 	}
827c209e3e2SJohn Baldwin 	p->p_oppid = 0;
828c209e3e2SJohn Baldwin 	PROC_UNLOCK(p);
829324fb6beSRobert Watson 
830324fb6beSRobert Watson 	/*
831324fb6beSRobert Watson 	 * Remove other references to this process to ensure we have an
832324fb6beSRobert Watson 	 * exclusive reference.
833324fb6beSRobert Watson 	 */
834324fb6beSRobert Watson 	sx_xlock(&allproc_lock);
835324fb6beSRobert Watson 	LIST_REMOVE(p, p_list);	/* off zombproc */
836324fb6beSRobert Watson 	sx_xunlock(&allproc_lock);
837324fb6beSRobert Watson 	LIST_REMOVE(p, p_sibling);
838237623b0SKonstantin Belousov 	reaper_abandon_children(p, true);
839237623b0SKonstantin Belousov 	LIST_REMOVE(p, p_reapsibling);
8407335ed90SKonstantin Belousov 	PROC_LOCK(p);
8412e39e24fSKonstantin Belousov 	clear_orphan(p);
8427335ed90SKonstantin Belousov 	PROC_UNLOCK(p);
843324fb6beSRobert Watson 	leavepgrp(p);
844cfb5f768SJonathan Anderson 	if (p->p_procdesc != NULL)
845cfb5f768SJonathan Anderson 		procdesc_reap(p);
846324fb6beSRobert Watson 	sx_xunlock(&proctree_lock);
847324fb6beSRobert Watson 
8489e590ff0SKonstantin Belousov 	PROC_LOCK(p);
8499e590ff0SKonstantin Belousov 	knlist_detach(p->p_klist);
8509e590ff0SKonstantin Belousov 	p->p_klist = NULL;
8519e590ff0SKonstantin Belousov 	PROC_UNLOCK(p);
8529e590ff0SKonstantin Belousov 
853324fb6beSRobert Watson 	/*
854fbe503d4SMateusz Guzik 	 * Removal from allproc list and process group list paired with
855fbe503d4SMateusz Guzik 	 * PROC_LOCK which was executed during that time should guarantee
856fbe503d4SMateusz Guzik 	 * nothing can reach this process anymore. As such further locking
857fbe503d4SMateusz Guzik 	 * is unnecessary.
858324fb6beSRobert Watson 	 */
859b4490c6eSKonstantin Belousov 	p->p_xexit = p->p_xsig = 0;		/* XXX: why? */
860fbe503d4SMateusz Guzik 
861324fb6beSRobert Watson 	PROC_LOCK(q);
862324fb6beSRobert Watson 	ruadd(&q->p_stats->p_cru, &q->p_crux, &p->p_ru, &p->p_rux);
863324fb6beSRobert Watson 	PROC_UNLOCK(q);
864324fb6beSRobert Watson 
865324fb6beSRobert Watson 	/*
866324fb6beSRobert Watson 	 * Decrement the count of procs running with this uid.
867324fb6beSRobert Watson 	 */
868324fb6beSRobert Watson 	(void)chgproccnt(p->p_ucred->cr_ruidinfo, -1, 0);
869324fb6beSRobert Watson 
870324fb6beSRobert Watson 	/*
871097055e2SEdward Tomasz Napierala 	 * Destroy resource accounting information associated with the process.
872097055e2SEdward Tomasz Napierala 	 */
873afcc55f3SEdward Tomasz Napierala #ifdef RACCT
8744b5c9cf6SEdward Tomasz Napierala 	if (racct_enable) {
875b38520f0SEdward Tomasz Napierala 		PROC_LOCK(p);
876b38520f0SEdward Tomasz Napierala 		racct_sub(p, RACCT_NPROC, 1);
877b38520f0SEdward Tomasz Napierala 		PROC_UNLOCK(p);
8784b5c9cf6SEdward Tomasz Napierala 	}
879afcc55f3SEdward Tomasz Napierala #endif
880b38520f0SEdward Tomasz Napierala 	racct_proc_exit(p);
881097055e2SEdward Tomasz Napierala 
882097055e2SEdward Tomasz Napierala 	/*
883324fb6beSRobert Watson 	 * Free credentials, arguments, and sigacts.
884324fb6beSRobert Watson 	 */
885324fb6beSRobert Watson 	crfree(p->p_ucred);
886daf63fd2SMateusz Guzik 	proc_set_cred(p, NULL);
887324fb6beSRobert Watson 	pargs_drop(p->p_args);
888324fb6beSRobert Watson 	p->p_args = NULL;
889324fb6beSRobert Watson 	sigacts_free(p->p_sigacts);
890324fb6beSRobert Watson 	p->p_sigacts = NULL;
891324fb6beSRobert Watson 
892324fb6beSRobert Watson 	/*
893324fb6beSRobert Watson 	 * Do any thread-system specific cleanups.
894324fb6beSRobert Watson 	 */
895324fb6beSRobert Watson 	thread_wait(p);
896324fb6beSRobert Watson 
897324fb6beSRobert Watson 	/*
898324fb6beSRobert Watson 	 * Give vm and machine-dependent layer a chance to free anything that
899324fb6beSRobert Watson 	 * cpu_exit couldn't release while still running in process context.
900324fb6beSRobert Watson 	 */
901324fb6beSRobert Watson 	vm_waitproc(p);
902324fb6beSRobert Watson #ifdef MAC
903324fb6beSRobert Watson 	mac_proc_destroy(p);
904324fb6beSRobert Watson #endif
9056520495aSAdrian Chadd 	/*
9066520495aSAdrian Chadd 	 * Free any domain policy that's still hiding around.
9076520495aSAdrian Chadd 	 */
9086520495aSAdrian Chadd 	vm_domain_policy_cleanup(&p->p_vm_dom_policy);
9096520495aSAdrian Chadd 
910324fb6beSRobert Watson 	KASSERT(FIRST_THREAD_IN_PROC(p),
911324fb6beSRobert Watson 	    ("proc_reap: no residual thread!"));
912324fb6beSRobert Watson 	uma_zfree(proc_zone, p);
9134b48959fSKonstantin Belousov 	atomic_add_int(&nprocs, -1);
914324fb6beSRobert Watson }
915324fb6beSRobert Watson 
916dcd43281SKonstantin Belousov static int
917f13b5a0fSKonstantin Belousov proc_to_reap(struct thread *td, struct proc *p, idtype_t idtype, id_t id,
91857c74f5bSJohn Baldwin     int *status, int options, struct __wrusage *wrusage, siginfo_t *siginfo,
91957c74f5bSJohn Baldwin     int check_only)
920dcd43281SKonstantin Belousov {
921f13b5a0fSKonstantin Belousov 	struct rusage *rup;
922dcd43281SKonstantin Belousov 
923db62ced2SJaakko Heinonen 	sx_assert(&proctree_lock, SA_XLOCKED);
924db62ced2SJaakko Heinonen 
925dcd43281SKonstantin Belousov 	PROC_LOCK(p);
926f13b5a0fSKonstantin Belousov 
927f13b5a0fSKonstantin Belousov 	switch (idtype) {
928f13b5a0fSKonstantin Belousov 	case P_ALL:
92953bf545dSMariusz Zaborski 		if (p->p_procdesc != NULL) {
93053bf545dSMariusz Zaborski 			PROC_UNLOCK(p);
93153bf545dSMariusz Zaborski 			return (0);
93253bf545dSMariusz Zaborski 		}
933f13b5a0fSKonstantin Belousov 		break;
934f13b5a0fSKonstantin Belousov 	case P_PID:
935f13b5a0fSKonstantin Belousov 		if (p->p_pid != (pid_t)id) {
936dcd43281SKonstantin Belousov 			PROC_UNLOCK(p);
937dcd43281SKonstantin Belousov 			return (0);
938dcd43281SKonstantin Belousov 		}
939f13b5a0fSKonstantin Belousov 		break;
940f13b5a0fSKonstantin Belousov 	case P_PGID:
941f13b5a0fSKonstantin Belousov 		if (p->p_pgid != (pid_t)id) {
942f13b5a0fSKonstantin Belousov 			PROC_UNLOCK(p);
943f13b5a0fSKonstantin Belousov 			return (0);
944f13b5a0fSKonstantin Belousov 		}
945f13b5a0fSKonstantin Belousov 		break;
946f13b5a0fSKonstantin Belousov 	case P_SID:
947f13b5a0fSKonstantin Belousov 		if (p->p_session->s_sid != (pid_t)id) {
948f13b5a0fSKonstantin Belousov 			PROC_UNLOCK(p);
949f13b5a0fSKonstantin Belousov 			return (0);
950f13b5a0fSKonstantin Belousov 		}
951f13b5a0fSKonstantin Belousov 		break;
952f13b5a0fSKonstantin Belousov 	case P_UID:
953f13b5a0fSKonstantin Belousov 		if (p->p_ucred->cr_uid != (uid_t)id) {
954f13b5a0fSKonstantin Belousov 			PROC_UNLOCK(p);
955f13b5a0fSKonstantin Belousov 			return (0);
956f13b5a0fSKonstantin Belousov 		}
957f13b5a0fSKonstantin Belousov 		break;
958f13b5a0fSKonstantin Belousov 	case P_GID:
959f13b5a0fSKonstantin Belousov 		if (p->p_ucred->cr_gid != (gid_t)id) {
960f13b5a0fSKonstantin Belousov 			PROC_UNLOCK(p);
961f13b5a0fSKonstantin Belousov 			return (0);
962f13b5a0fSKonstantin Belousov 		}
963f13b5a0fSKonstantin Belousov 		break;
964f13b5a0fSKonstantin Belousov 	case P_JAILID:
965b1051d92SMateusz Guzik 		if (p->p_ucred->cr_prison->pr_id != (int)id) {
966f13b5a0fSKonstantin Belousov 			PROC_UNLOCK(p);
967f13b5a0fSKonstantin Belousov 			return (0);
968f13b5a0fSKonstantin Belousov 		}
969f13b5a0fSKonstantin Belousov 		break;
970f13b5a0fSKonstantin Belousov 	/*
971f13b5a0fSKonstantin Belousov 	 * It seems that the thread structures get zeroed out
972f13b5a0fSKonstantin Belousov 	 * at process exit.  This makes it impossible to
973f13b5a0fSKonstantin Belousov 	 * support P_SETID, P_CID or P_CPUID.
974f13b5a0fSKonstantin Belousov 	 */
975f13b5a0fSKonstantin Belousov 	default:
976f13b5a0fSKonstantin Belousov 		PROC_UNLOCK(p);
977f13b5a0fSKonstantin Belousov 		return (0);
978f13b5a0fSKonstantin Belousov 	}
979f13b5a0fSKonstantin Belousov 
980dcd43281SKonstantin Belousov 	if (p_canwait(td, p)) {
981dcd43281SKonstantin Belousov 		PROC_UNLOCK(p);
982dcd43281SKonstantin Belousov 		return (0);
983dcd43281SKonstantin Belousov 	}
984dcd43281SKonstantin Belousov 
985f13b5a0fSKonstantin Belousov 	if (((options & WEXITED) == 0) && (p->p_state == PRS_ZOMBIE)) {
986f13b5a0fSKonstantin Belousov 		PROC_UNLOCK(p);
987f13b5a0fSKonstantin Belousov 		return (0);
988f13b5a0fSKonstantin Belousov 	}
989f13b5a0fSKonstantin Belousov 
990dcd43281SKonstantin Belousov 	/*
991dcd43281SKonstantin Belousov 	 * This special case handles a kthread spawned by linux_clone
992dcd43281SKonstantin Belousov 	 * (see linux_misc.c).  The linux_wait4 and linux_waitpid
993dcd43281SKonstantin Belousov 	 * functions need to be able to distinguish between waiting
994dcd43281SKonstantin Belousov 	 * on a process and waiting on a thread.  It is a thread if
995dcd43281SKonstantin Belousov 	 * p_sigparent is not SIGCHLD, and the WLINUXCLONE option
996dcd43281SKonstantin Belousov 	 * signifies we want to wait for threads and not processes.
997dcd43281SKonstantin Belousov 	 */
998dcd43281SKonstantin Belousov 	if ((p->p_sigparent != SIGCHLD) ^
999dcd43281SKonstantin Belousov 	    ((options & WLINUXCLONE) != 0)) {
1000dcd43281SKonstantin Belousov 		PROC_UNLOCK(p);
1001dcd43281SKonstantin Belousov 		return (0);
1002dcd43281SKonstantin Belousov 	}
1003dcd43281SKonstantin Belousov 
1004f13b5a0fSKonstantin Belousov 	if (siginfo != NULL) {
1005f13b5a0fSKonstantin Belousov 		bzero(siginfo, sizeof(*siginfo));
1006f13b5a0fSKonstantin Belousov 		siginfo->si_errno = 0;
1007f13b5a0fSKonstantin Belousov 
1008f13b5a0fSKonstantin Belousov 		/*
1009f13b5a0fSKonstantin Belousov 		 * SUSv4 requires that the si_signo value is always
1010f13b5a0fSKonstantin Belousov 		 * SIGCHLD. Obey it despite the rfork(2) interface
1011f13b5a0fSKonstantin Belousov 		 * allows to request other signal for child exit
1012f13b5a0fSKonstantin Belousov 		 * notification.
1013f13b5a0fSKonstantin Belousov 		 */
1014f13b5a0fSKonstantin Belousov 		siginfo->si_signo = SIGCHLD;
1015f13b5a0fSKonstantin Belousov 
1016f13b5a0fSKonstantin Belousov 		/*
1017f13b5a0fSKonstantin Belousov 		 *  This is still a rough estimate.  We will fix the
1018f13b5a0fSKonstantin Belousov 		 *  cases TRAPPED, STOPPED, and CONTINUED later.
1019f13b5a0fSKonstantin Belousov 		 */
1020b4490c6eSKonstantin Belousov 		if (WCOREDUMP(p->p_xsig)) {
1021f13b5a0fSKonstantin Belousov 			siginfo->si_code = CLD_DUMPED;
1022b4490c6eSKonstantin Belousov 			siginfo->si_status = WTERMSIG(p->p_xsig);
1023b4490c6eSKonstantin Belousov 		} else if (WIFSIGNALED(p->p_xsig)) {
1024f13b5a0fSKonstantin Belousov 			siginfo->si_code = CLD_KILLED;
1025b4490c6eSKonstantin Belousov 			siginfo->si_status = WTERMSIG(p->p_xsig);
1026b20a9aa9SJilles Tjoelker 		} else {
1027f13b5a0fSKonstantin Belousov 			siginfo->si_code = CLD_EXITED;
1028b4490c6eSKonstantin Belousov 			siginfo->si_status = p->p_xexit;
1029b20a9aa9SJilles Tjoelker 		}
1030f13b5a0fSKonstantin Belousov 
1031f13b5a0fSKonstantin Belousov 		siginfo->si_pid = p->p_pid;
1032f13b5a0fSKonstantin Belousov 		siginfo->si_uid = p->p_ucred->cr_uid;
1033f13b5a0fSKonstantin Belousov 
1034f13b5a0fSKonstantin Belousov 		/*
1035f13b5a0fSKonstantin Belousov 		 * The si_addr field would be useful additional
1036f13b5a0fSKonstantin Belousov 		 * detail, but apparently the PC value may be lost
1037f13b5a0fSKonstantin Belousov 		 * when we reach this point.  bzero() above sets
1038f13b5a0fSKonstantin Belousov 		 * siginfo->si_addr to NULL.
1039f13b5a0fSKonstantin Belousov 		 */
1040f13b5a0fSKonstantin Belousov 	}
1041f13b5a0fSKonstantin Belousov 
1042f13b5a0fSKonstantin Belousov 	/*
1043f13b5a0fSKonstantin Belousov 	 * There should be no reason to limit resources usage info to
1044f13b5a0fSKonstantin Belousov 	 * exited processes only.  A snapshot about any resources used
1045f13b5a0fSKonstantin Belousov 	 * by a stopped process may be exactly what is needed.
1046f13b5a0fSKonstantin Belousov 	 */
1047f13b5a0fSKonstantin Belousov 	if (wrusage != NULL) {
1048f13b5a0fSKonstantin Belousov 		rup = &wrusage->wru_self;
1049f13b5a0fSKonstantin Belousov 		*rup = p->p_ru;
10505c7bebf9SKonstantin Belousov 		PROC_STATLOCK(p);
1051f13b5a0fSKonstantin Belousov 		calcru(p, &rup->ru_utime, &rup->ru_stime);
10525c7bebf9SKonstantin Belousov 		PROC_STATUNLOCK(p);
1053f13b5a0fSKonstantin Belousov 
1054f13b5a0fSKonstantin Belousov 		rup = &wrusage->wru_children;
1055f13b5a0fSKonstantin Belousov 		*rup = p->p_stats->p_cru;
1056f13b5a0fSKonstantin Belousov 		calccru(p, &rup->ru_utime, &rup->ru_stime);
1057f13b5a0fSKonstantin Belousov 	}
1058f13b5a0fSKonstantin Belousov 
105957c74f5bSJohn Baldwin 	if (p->p_state == PRS_ZOMBIE && !check_only) {
10605c7bebf9SKonstantin Belousov 		PROC_SLOCK(p);
1061f13b5a0fSKonstantin Belousov 		proc_reap(td, p, status, options);
1062dcd43281SKonstantin Belousov 		return (-1);
1063dcd43281SKonstantin Belousov 	}
1064dcd43281SKonstantin Belousov 	PROC_UNLOCK(p);
1065dcd43281SKonstantin Belousov 	return (1);
1066dcd43281SKonstantin Belousov }
1067dcd43281SKonstantin Belousov 
1068b7e23e82SJohn Baldwin int
10697eaec467SJohn Baldwin kern_wait(struct thread *td, pid_t pid, int *status, int options,
10707eaec467SJohn Baldwin     struct rusage *rusage)
1071df8bae1dSRodney W. Grimes {
1072f13b5a0fSKonstantin Belousov 	struct __wrusage wru, *wrup;
1073f13b5a0fSKonstantin Belousov 	idtype_t idtype;
1074f13b5a0fSKonstantin Belousov 	id_t id;
1075f13b5a0fSKonstantin Belousov 	int ret;
1076f13b5a0fSKonstantin Belousov 
1077538375d4SKonstantin Belousov 	/*
1078538375d4SKonstantin Belousov 	 * Translate the special pid values into the (idtype, pid)
1079538375d4SKonstantin Belousov 	 * pair for kern_wait6.  The WAIT_MYPGRP case is handled by
1080538375d4SKonstantin Belousov 	 * kern_wait6() on its own.
1081538375d4SKonstantin Belousov 	 */
1082f13b5a0fSKonstantin Belousov 	if (pid == WAIT_ANY) {
1083f13b5a0fSKonstantin Belousov 		idtype = P_ALL;
1084f13b5a0fSKonstantin Belousov 		id = 0;
1085ea293f3fSKonstantin Belousov 	} else if (pid < 0) {
1086f13b5a0fSKonstantin Belousov 		idtype = P_PGID;
1087f13b5a0fSKonstantin Belousov 		id = (id_t)-pid;
1088ea293f3fSKonstantin Belousov 	} else {
1089f13b5a0fSKonstantin Belousov 		idtype = P_PID;
1090f13b5a0fSKonstantin Belousov 		id = (id_t)pid;
1091f13b5a0fSKonstantin Belousov 	}
1092538375d4SKonstantin Belousov 
1093f13b5a0fSKonstantin Belousov 	if (rusage != NULL)
1094f13b5a0fSKonstantin Belousov 		wrup = &wru;
1095f13b5a0fSKonstantin Belousov 	else
1096f13b5a0fSKonstantin Belousov 		wrup = NULL;
1097538375d4SKonstantin Belousov 
1098f13b5a0fSKonstantin Belousov 	/*
1099f13b5a0fSKonstantin Belousov 	 * For backward compatibility we implicitly add flags WEXITED
1100f13b5a0fSKonstantin Belousov 	 * and WTRAPPED here.
1101f13b5a0fSKonstantin Belousov 	 */
1102f13b5a0fSKonstantin Belousov 	options |= WEXITED | WTRAPPED;
1103f13b5a0fSKonstantin Belousov 	ret = kern_wait6(td, idtype, id, status, options, wrup, NULL);
1104f13b5a0fSKonstantin Belousov 	if (rusage != NULL)
1105f13b5a0fSKonstantin Belousov 		*rusage = wru.wru_self;
1106f13b5a0fSKonstantin Belousov 	return (ret);
1107f13b5a0fSKonstantin Belousov }
1108f13b5a0fSKonstantin Belousov 
1109f13b5a0fSKonstantin Belousov int
1110f13b5a0fSKonstantin Belousov kern_wait6(struct thread *td, idtype_t idtype, id_t id, int *status,
1111f13b5a0fSKonstantin Belousov     int options, struct __wrusage *wrusage, siginfo_t *siginfo)
1112f13b5a0fSKonstantin Belousov {
1113324fb6beSRobert Watson 	struct proc *p, *q;
11143a41ec6aSEd Schouten 	pid_t pid;
1115dcd43281SKonstantin Belousov 	int error, nfound, ret;
1116df8bae1dSRodney W. Grimes 
1117f13b5a0fSKonstantin Belousov 	AUDIT_ARG_VALUE((int)idtype);	/* XXX - This is likely wrong! */
1118f13b5a0fSKonstantin Belousov 	AUDIT_ARG_PID((pid_t)id);	/* XXX - This may be wrong! */
11192ef24ddeSRobert Watson 	AUDIT_ARG_VALUE(options);
1120de3007e8SWayne Salamon 
1121b40ce416SJulian Elischer 	q = td->td_proc;
1122f13b5a0fSKonstantin Belousov 
1123a2a85596SKonstantin Belousov 	if ((pid_t)id == WAIT_MYPGRP && (idtype == P_PID || idtype == P_PGID)) {
1124a545089eSKonstantin Belousov 		PROC_LOCK(q);
1125f13b5a0fSKonstantin Belousov 		id = (id_t)q->p_pgid;
1126a545089eSKonstantin Belousov 		PROC_UNLOCK(q);
1127f13b5a0fSKonstantin Belousov 		idtype = P_PGID;
1128f591779bSSeigo Tanimura 	}
1129f13b5a0fSKonstantin Belousov 
1130f528c3fdSDavid E. O'Brien 	/* If we don't know the option, just return. */
1131f13b5a0fSKonstantin Belousov 	if ((options & ~(WUNTRACED | WNOHANG | WCONTINUED | WNOWAIT |
1132f13b5a0fSKonstantin Belousov 	    WEXITED | WTRAPPED | WLINUXCLONE)) != 0)
11336dc958b9SJohn Baldwin 		return (EINVAL);
1134f13b5a0fSKonstantin Belousov 	if ((options & (WEXITED | WUNTRACED | WCONTINUED | WTRAPPED)) == 0) {
1135f13b5a0fSKonstantin Belousov 		/*
1136f13b5a0fSKonstantin Belousov 		 * We will be unable to find any matching processes,
1137f13b5a0fSKonstantin Belousov 		 * because there are no known events to look for.
1138f13b5a0fSKonstantin Belousov 		 * Prefer to return error instead of blocking
1139f13b5a0fSKonstantin Belousov 		 * indefinitely.
1140f13b5a0fSKonstantin Belousov 		 */
1141f13b5a0fSKonstantin Belousov 		return (EINVAL);
1142f13b5a0fSKonstantin Belousov 	}
1143f13b5a0fSKonstantin Belousov 
1144df8bae1dSRodney W. Grimes loop:
1145902c0d82SDavid Xu 	if (q->p_flag & P_STATCHILD) {
1146902c0d82SDavid Xu 		PROC_LOCK(q);
1147902c0d82SDavid Xu 		q->p_flag &= ~P_STATCHILD;
1148902c0d82SDavid Xu 		PROC_UNLOCK(q);
1149902c0d82SDavid Xu 	}
1150df8bae1dSRodney W. Grimes 	nfound = 0;
1151d7aadbf9SJohn Baldwin 	sx_xlock(&proctree_lock);
11522e3c8fcbSPoul-Henning Kamp 	LIST_FOREACH(p, &q->p_children, p_sibling) {
11533a41ec6aSEd Schouten 		pid = p->p_pid;
1154f13b5a0fSKonstantin Belousov 		ret = proc_to_reap(td, p, idtype, id, status, options,
115557c74f5bSJohn Baldwin 		    wrusage, siginfo, 0);
1156dcd43281SKonstantin Belousov 		if (ret == 0)
1157df8bae1dSRodney W. Grimes 			continue;
1158dcd43281SKonstantin Belousov 		else if (ret == 1)
1159df8bae1dSRodney W. Grimes 			nfound++;
11603a41ec6aSEd Schouten 		else {
11613a41ec6aSEd Schouten 			td->td_retval[0] = pid;
1162d7aadbf9SJohn Baldwin 			return (0);
11633a41ec6aSEd Schouten 		}
1164dcd43281SKonstantin Belousov 
1165dcd43281SKonstantin Belousov 		PROC_LOCK(p);
1166dcd43281SKonstantin Belousov 		PROC_SLOCK(p);
1167f13b5a0fSKonstantin Belousov 
1168f13b5a0fSKonstantin Belousov 		if ((options & WTRAPPED) != 0 &&
1169f13b5a0fSKonstantin Belousov 		    (p->p_flag & P_TRACED) != 0 &&
1170f13b5a0fSKonstantin Belousov 		    (p->p_flag & (P_STOPPED_TRACE | P_STOPPED_SIG)) != 0 &&
11715a2f73e6SDavid Xu 		    (p->p_suspcount == p->p_numthreads) &&
1172f13b5a0fSKonstantin Belousov 		    ((p->p_flag & P_WAITED) == 0)) {
1173982d11f8SJeff Roberson 			PROC_SUNLOCK(p);
1174f13b5a0fSKonstantin Belousov 			if ((options & WNOWAIT) == 0)
1175df8bae1dSRodney W. Grimes 				p->p_flag |= P_WAITED;
1176d7aadbf9SJohn Baldwin 			sx_xunlock(&proctree_lock);
1177ebceaf6dSDavid Xu 
1178f13b5a0fSKonstantin Belousov 			if (status != NULL)
1179b4490c6eSKonstantin Belousov 				*status = W_STOPCODE(p->p_xsig);
1180f13b5a0fSKonstantin Belousov 			if (siginfo != NULL) {
1181b4490c6eSKonstantin Belousov 				siginfo->si_status = p->p_xsig;
1182f13b5a0fSKonstantin Belousov 				siginfo->si_code = CLD_TRAPPED;
1183f13b5a0fSKonstantin Belousov 			}
1184f13b5a0fSKonstantin Belousov 			if ((options & WNOWAIT) == 0) {
1185ebceaf6dSDavid Xu 				PROC_LOCK(q);
1186ebceaf6dSDavid Xu 				sigqueue_take(p->p_ksi);
1187ebceaf6dSDavid Xu 				PROC_UNLOCK(q);
1188f13b5a0fSKonstantin Belousov 			}
1189ebceaf6dSDavid Xu 
1190515b7a0bSJohn Baldwin 			CTR4(KTR_PTRACE,
1191515b7a0bSJohn Baldwin 	    "wait: returning trapped pid %d status %#x (xstat %d) xthread %d",
1192b4490c6eSKonstantin Belousov 			    p->p_pid, W_STOPCODE(p->p_xsig), p->p_xsig,
1193515b7a0bSJohn Baldwin 			    p->p_xthread != NULL ? p->p_xthread->td_tid : -1);
1194f13b5a0fSKonstantin Belousov 			PROC_UNLOCK(p);
11953a41ec6aSEd Schouten 			td->td_retval[0] = pid;
1196f13b5a0fSKonstantin Belousov 			return (0);
1197f13b5a0fSKonstantin Belousov 		}
1198f13b5a0fSKonstantin Belousov 		if ((options & WUNTRACED) != 0 &&
1199f13b5a0fSKonstantin Belousov 		    (p->p_flag & P_STOPPED_SIG) != 0 &&
1200f13b5a0fSKonstantin Belousov 		    (p->p_suspcount == p->p_numthreads) &&
1201f13b5a0fSKonstantin Belousov 		    ((p->p_flag & P_WAITED) == 0)) {
1202f13b5a0fSKonstantin Belousov 			PROC_SUNLOCK(p);
1203f13b5a0fSKonstantin Belousov 			if ((options & WNOWAIT) == 0)
1204f13b5a0fSKonstantin Belousov 				p->p_flag |= P_WAITED;
1205f13b5a0fSKonstantin Belousov 			sx_xunlock(&proctree_lock);
1206f13b5a0fSKonstantin Belousov 
1207f13b5a0fSKonstantin Belousov 			if (status != NULL)
1208b4490c6eSKonstantin Belousov 				*status = W_STOPCODE(p->p_xsig);
1209f13b5a0fSKonstantin Belousov 			if (siginfo != NULL) {
1210b4490c6eSKonstantin Belousov 				siginfo->si_status = p->p_xsig;
1211f13b5a0fSKonstantin Belousov 				siginfo->si_code = CLD_STOPPED;
1212f13b5a0fSKonstantin Belousov 			}
1213f13b5a0fSKonstantin Belousov 			if ((options & WNOWAIT) == 0) {
1214f13b5a0fSKonstantin Belousov 				PROC_LOCK(q);
1215f13b5a0fSKonstantin Belousov 				sigqueue_take(p->p_ksi);
1216f13b5a0fSKonstantin Belousov 				PROC_UNLOCK(q);
1217f13b5a0fSKonstantin Belousov 			}
1218f13b5a0fSKonstantin Belousov 
1219f13b5a0fSKonstantin Belousov 			PROC_UNLOCK(p);
12203a41ec6aSEd Schouten 			td->td_retval[0] = pid;
1221b7e23e82SJohn Baldwin 			return (0);
1222df8bae1dSRodney W. Grimes 		}
1223982d11f8SJeff Roberson 		PROC_SUNLOCK(p);
1224f13b5a0fSKonstantin Belousov 		if ((options & WCONTINUED) != 0 &&
1225f13b5a0fSKonstantin Belousov 		    (p->p_flag & P_CONTINUED) != 0) {
12266ee093fbSMike Barcroft 			sx_xunlock(&proctree_lock);
1227f13b5a0fSKonstantin Belousov 			if ((options & WNOWAIT) == 0) {
12286ee093fbSMike Barcroft 				p->p_flag &= ~P_CONTINUED;
1229ebceaf6dSDavid Xu 				PROC_LOCK(q);
1230ebceaf6dSDavid Xu 				sigqueue_take(p->p_ksi);
1231ebceaf6dSDavid Xu 				PROC_UNLOCK(q);
1232f13b5a0fSKonstantin Belousov 			}
1233e94cc4acSDavid Xu 			PROC_UNLOCK(p);
1234ebceaf6dSDavid Xu 
1235f13b5a0fSKonstantin Belousov 			if (status != NULL)
1236b7e23e82SJohn Baldwin 				*status = SIGCONT;
1237f13b5a0fSKonstantin Belousov 			if (siginfo != NULL) {
1238f13b5a0fSKonstantin Belousov 				siginfo->si_status = SIGCONT;
1239f13b5a0fSKonstantin Belousov 				siginfo->si_code = CLD_CONTINUED;
1240f13b5a0fSKonstantin Belousov 			}
12413a41ec6aSEd Schouten 			td->td_retval[0] = pid;
1242dcdc6c36SKonstantin Belousov 			return (0);
12436ee093fbSMike Barcroft 		}
1244d7aadbf9SJohn Baldwin 		PROC_UNLOCK(p);
1245d7aadbf9SJohn Baldwin 	}
1246dcd43281SKonstantin Belousov 
1247dcd43281SKonstantin Belousov 	/*
1248dcd43281SKonstantin Belousov 	 * Look in the orphans list too, to allow the parent to
1249dcd43281SKonstantin Belousov 	 * collect it's child exit status even if child is being
1250dcd43281SKonstantin Belousov 	 * debugged.
1251dcd43281SKonstantin Belousov 	 *
1252dcd43281SKonstantin Belousov 	 * Debugger detaches from the parent upon successful
1253dcd43281SKonstantin Belousov 	 * switch-over from parent to child.  At this point due to
1254dcd43281SKonstantin Belousov 	 * re-parenting the parent loses the child to debugger and a
1255dcd43281SKonstantin Belousov 	 * wait4(2) call would report that it has no children to wait
1256dcd43281SKonstantin Belousov 	 * for.  By maintaining a list of orphans we allow the parent
1257dcd43281SKonstantin Belousov 	 * to successfully wait until the child becomes a zombie.
1258dcd43281SKonstantin Belousov 	 */
125957c74f5bSJohn Baldwin 	if (nfound == 0) {
1260dcd43281SKonstantin Belousov 		LIST_FOREACH(p, &q->p_orphans, p_orphan) {
126157c74f5bSJohn Baldwin 			ret = proc_to_reap(td, p, idtype, id, NULL, options,
126257c74f5bSJohn Baldwin 			    NULL, NULL, 1);
126357c74f5bSJohn Baldwin 			if (ret != 0) {
126457c74f5bSJohn Baldwin 				KASSERT(ret != -1, ("reaped an orphan (pid %d)",
126557c74f5bSJohn Baldwin 				    (int)td->td_retval[0]));
1266dcd43281SKonstantin Belousov 				nfound++;
126757c74f5bSJohn Baldwin 				break;
126857c74f5bSJohn Baldwin 			}
126957c74f5bSJohn Baldwin 		}
1270dcd43281SKonstantin Belousov 	}
1271d7aadbf9SJohn Baldwin 	if (nfound == 0) {
1272d7aadbf9SJohn Baldwin 		sx_xunlock(&proctree_lock);
1273d7aadbf9SJohn Baldwin 		return (ECHILD);
1274d7aadbf9SJohn Baldwin 	}
1275b7e23e82SJohn Baldwin 	if (options & WNOHANG) {
1276d7aadbf9SJohn Baldwin 		sx_xunlock(&proctree_lock);
1277d7aadbf9SJohn Baldwin 		td->td_retval[0] = 0;
1278d7aadbf9SJohn Baldwin 		return (0);
1279d7aadbf9SJohn Baldwin 	}
1280d7aadbf9SJohn Baldwin 	PROC_LOCK(q);
1281d7aadbf9SJohn Baldwin 	sx_xunlock(&proctree_lock);
128295992d56SDavid Xu 	if (q->p_flag & P_STATCHILD) {
128395992d56SDavid Xu 		q->p_flag &= ~P_STATCHILD;
128495992d56SDavid Xu 		error = 0;
128595992d56SDavid Xu 	} else
12867f05b035SAlfred Perlstein 		error = msleep(q, &q->p_mtx, PWAIT | PCATCH, "wait", 0);
1287d7aadbf9SJohn Baldwin 	PROC_UNLOCK(q);
12884ae89b95SJohn Baldwin 	if (error)
1289d7aadbf9SJohn Baldwin 		return (error);
1290d7aadbf9SJohn Baldwin 	goto loop;
1291d7aadbf9SJohn Baldwin }
1292df8bae1dSRodney W. Grimes 
1293df8bae1dSRodney W. Grimes /*
129498f03f90SJake Burkholder  * Make process 'parent' the new parent of process 'child'.
129598f03f90SJake Burkholder  * Must be called with an exclusive hold of proctree lock.
1296df8bae1dSRodney W. Grimes  */
1297df8bae1dSRodney W. Grimes void
1298830c3153SDag-Erling Smørgrav proc_reparent(struct proc *child, struct proc *parent)
1299df8bae1dSRodney W. Grimes {
1300df8bae1dSRodney W. Grimes 
13014e5e677bSJohn Baldwin 	sx_assert(&proctree_lock, SX_XLOCKED);
1302c65437a3SJohn Baldwin 	PROC_LOCK_ASSERT(child, MA_OWNED);
1303df8bae1dSRodney W. Grimes 	if (child->p_pptr == parent)
1304df8bae1dSRodney W. Grimes 		return;
1305df8bae1dSRodney W. Grimes 
1306ff766807SDavid Xu 	PROC_LOCK(child->p_pptr);
1307ff766807SDavid Xu 	sigqueue_take(child->p_ksi);
1308ff766807SDavid Xu 	PROC_UNLOCK(child->p_pptr);
1309b75356e1SJeffrey Hsu 	LIST_REMOVE(child, p_sibling);
1310b75356e1SJeffrey Hsu 	LIST_INSERT_HEAD(&parent->p_children, child, p_sibling);
1311dcd43281SKonstantin Belousov 
13122e39e24fSKonstantin Belousov 	clear_orphan(child);
1313dcd43281SKonstantin Belousov 	if (child->p_flag & P_TRACED) {
1314d7359980SKonstantin Belousov 		if (LIST_EMPTY(&child->p_pptr->p_orphans)) {
1315d7359980SKonstantin Belousov 			child->p_treeflag |= P_TREE_FIRST_ORPHAN;
1316d7359980SKonstantin Belousov 			LIST_INSERT_HEAD(&child->p_pptr->p_orphans, child,
1317d7359980SKonstantin Belousov 			    p_orphan);
1318d7359980SKonstantin Belousov 		} else {
1319ba78d6b7SMark Johnston 			LIST_INSERT_AFTER(LIST_FIRST(&child->p_pptr->p_orphans),
1320ba78d6b7SMark Johnston 			    child, p_orphan);
1321d7359980SKonstantin Belousov 		}
1322d7359980SKonstantin Belousov 		child->p_treeflag |= P_TREE_ORPHANED;
1323dcd43281SKonstantin Belousov 	}
1324dcd43281SKonstantin Belousov 
1325df8bae1dSRodney W. Grimes 	child->p_pptr = parent;
1326df8bae1dSRodney W. Grimes }
1327