1996c772fSJohn Dyson /* 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. 18df8bae1dSRodney W. Grimes * 3. All advertising materials mentioning features or use of this software 19df8bae1dSRodney W. Grimes * must display the following acknowledgement: 20df8bae1dSRodney W. Grimes * This product includes software developed by the University of 21df8bae1dSRodney W. Grimes * California, Berkeley and its contributors. 22df8bae1dSRodney W. Grimes * 4. Neither the name of the University nor the names of its contributors 23df8bae1dSRodney W. Grimes * may be used to endorse or promote products derived from this software 24df8bae1dSRodney W. Grimes * without specific prior written permission. 25df8bae1dSRodney W. Grimes * 26df8bae1dSRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27df8bae1dSRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28df8bae1dSRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29df8bae1dSRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30df8bae1dSRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31df8bae1dSRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32df8bae1dSRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33df8bae1dSRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34df8bae1dSRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35df8bae1dSRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36df8bae1dSRodney W. Grimes * SUCH DAMAGE. 37df8bae1dSRodney W. Grimes * 38df8bae1dSRodney W. Grimes * @(#)kern_exit.c 8.7 (Berkeley) 2/12/94 39c3aac50fSPeter Wemm * $FreeBSD$ 40df8bae1dSRodney W. Grimes */ 41df8bae1dSRodney W. Grimes 425591b823SEivind Eklund #include "opt_compat.h" 43db6a20e2SGarrett Wollman #include "opt_ktrace.h" 442555374cSRobert Watson #include "opt_mac.h" 45db6a20e2SGarrett Wollman 46df8bae1dSRodney W. Grimes #include <sys/param.h> 47df8bae1dSRodney W. Grimes #include <sys/systm.h> 485fdb8324SBruce Evans #include <sys/sysproto.h> 491c5bb3eaSPeter Wemm #include <sys/kernel.h> 50a1c995b6SPoul-Henning Kamp #include <sys/malloc.h> 51f34fa851SJohn Baldwin #include <sys/lock.h> 5235e0e5b3SJohn Baldwin #include <sys/mutex.h> 53df8bae1dSRodney W. Grimes #include <sys/proc.h> 542a024a2bSSean Eric Fagan #include <sys/pioctl.h> 55df8bae1dSRodney W. Grimes #include <sys/tty.h> 56df8bae1dSRodney W. Grimes #include <sys/wait.h> 57eb30c1c0SPeter Wemm #include <sys/vmmeter.h> 587a6b989bSJohn Baldwin #include <sys/vnode.h> 59df8bae1dSRodney W. Grimes #include <sys/resourcevar.h> 60797f2d22SPoul-Henning Kamp #include <sys/signalvar.h> 61b43179fbSJeff Roberson #include <sys/sched.h> 621005a129SJohn Baldwin #include <sys/sx.h> 63df8bae1dSRodney W. Grimes #include <sys/ptrace.h> 647c409b8aSJeffrey Hsu #include <sys/acct.h> /* for acct_process() function prototype */ 65797f2d22SPoul-Henning Kamp #include <sys/filedesc.h> 662555374cSRobert Watson #include <sys/mac.h> 67780dc5a8SPeter Wemm #include <sys/shm.h> 68780dc5a8SPeter Wemm #include <sys/sem.h> 6975c13541SPoul-Henning Kamp #include <sys/jail.h> 706c84de02SJohn Baldwin #ifdef KTRACE 716c84de02SJohn Baldwin #include <sys/ktrace.h> 726c84de02SJohn Baldwin #endif 73780dc5a8SPeter Wemm 74df8bae1dSRodney W. Grimes #include <vm/vm.h> 75eb30c1c0SPeter Wemm #include <vm/vm_extern.h> 767a6b989bSJohn Baldwin #include <vm/vm_param.h> 77efeaf95aSDavid Greenman #include <vm/pmap.h> 78efeaf95aSDavid Greenman #include <vm/vm_map.h> 792d21129dSAlan Cox #include <vm/vm_page.h> 80c897b813SJeff Roberson #include <vm/uma.h> 81dc9c271aSJulian Elischer #include <sys/user.h> 82df8bae1dSRodney W. Grimes 83ba198b1cSMark Newton /* Required to be non-static for SysVR4 emulator */ 8469a6f20bSMark Newton MALLOC_DEFINE(M_ZOMBIE, "zombie", "zombie proc status"); 8555166637SPoul-Henning Kamp 8693efcae8SPoul-Henning Kamp static MALLOC_DEFINE(M_ATEXIT, "atexit", "atexit callback"); 8793efcae8SPoul-Henning Kamp 884d77a549SAlfred Perlstein static int wait1(struct thread *, struct wait_args *, int); 895fdb8324SBruce Evans 90df8bae1dSRodney W. Grimes /* 91fed06968SJulian Elischer * callout list for things to do at exit time 92fed06968SJulian Elischer */ 9393efcae8SPoul-Henning Kamp struct exitlist { 94fed06968SJulian Elischer exitlist_fn function; 95e3975643SJake Burkholder TAILQ_ENTRY(exitlist) next; 9693efcae8SPoul-Henning Kamp }; 97fed06968SJulian Elischer 98e3975643SJake Burkholder TAILQ_HEAD(exit_list_head, exitlist); 9993efcae8SPoul-Henning Kamp static struct exit_list_head exit_list = TAILQ_HEAD_INITIALIZER(exit_list); 100fed06968SJulian Elischer 101fed06968SJulian Elischer /* 102df8bae1dSRodney W. Grimes * exit -- 103df8bae1dSRodney W. Grimes * Death of process. 104234216efSMatthew Dillon * 105234216efSMatthew Dillon * MPSAFE 106df8bae1dSRodney W. Grimes */ 107fc0b1dbfSBruce Evans void 108b40ce416SJulian Elischer sys_exit(td, uap) 109b40ce416SJulian Elischer struct thread *td; 110ac2b067bSPeter Wemm struct sys_exit_args /* { 1115fdb8324SBruce Evans int rval; 1125fdb8324SBruce Evans } */ *uap; 113df8bae1dSRodney W. Grimes { 114b40ce416SJulian Elischer 115234216efSMatthew Dillon mtx_lock(&Giant); 116b40ce416SJulian Elischer exit1(td, W_EXITCODE(uap->rval, 0)); 117df8bae1dSRodney W. Grimes /* NOTREACHED */ 118df8bae1dSRodney W. Grimes } 119df8bae1dSRodney W. Grimes 120df8bae1dSRodney W. Grimes /* 121df8bae1dSRodney W. Grimes * Exit: deallocate address space and other resources, change proc state 122df8bae1dSRodney W. Grimes * to zombie, and unlink proc from allproc and parent's lists. Save exit 123df8bae1dSRodney W. Grimes * status and rusage for wait(). Check for child processes and orphan them. 124df8bae1dSRodney W. Grimes */ 125fc0b1dbfSBruce Evans void 126b40ce416SJulian Elischer exit1(td, rv) 127b40ce416SJulian Elischer register struct thread *td; 128df8bae1dSRodney W. Grimes int rv; 129df8bae1dSRodney W. Grimes { 130276c5169SJohn Baldwin struct exitlist *ep; 131276c5169SJohn Baldwin struct proc *p, *nq, *q; 132276c5169SJohn Baldwin struct tty *tp; 133276c5169SJohn Baldwin struct vnode *ttyvp; 134df8bae1dSRodney W. Grimes register struct vmspace *vm; 13579deba82SMatthew Dillon struct vnode *vtmp; 136d7aadbf9SJohn Baldwin #ifdef KTRACE 137d7aadbf9SJohn Baldwin struct vnode *tracevp; 138d7aadbf9SJohn Baldwin #endif 139df8bae1dSRodney W. Grimes 1400cddd8f0SMatthew Dillon GIANT_REQUIRED; 1410cddd8f0SMatthew Dillon 142276c5169SJohn Baldwin p = td->td_proc; 143e746d950SJohn Baldwin if (p == initproc) { 1445f7bd355SPoul-Henning Kamp printf("init died (signal %d, exit %d)\n", 145df8bae1dSRodney W. Grimes WTERMSIG(rv), WEXITSTATUS(rv)); 1465f7bd355SPoul-Henning Kamp panic("Going nowhere without my init!"); 1475f7bd355SPoul-Henning Kamp } 1482c1011f7SJohn Dyson 1497a6b989bSJohn Baldwin /* 1506f8132a8SJulian Elischer * XXXXKSE: MUST abort all other threads before proceeding past here. 1517a6b989bSJohn Baldwin */ 152e602ba25SJulian Elischer PROC_LOCK(p); 153e602ba25SJulian Elischer if (p->p_flag & P_KSES) { 154e602ba25SJulian Elischer /* 155e602ba25SJulian Elischer * First check if some other thread got here before us.. 156e602ba25SJulian Elischer * if so, act apropriatly, (exit or suspend); 157e602ba25SJulian Elischer */ 158e602ba25SJulian Elischer thread_suspend_check(0); 1596f8132a8SJulian Elischer /* 1606f8132a8SJulian Elischer * Here is a trick.. 1616f8132a8SJulian Elischer * We need to free up our KSE to process other threads 1626f8132a8SJulian Elischer * so that we can safely set the UNBOUND flag 1636f8132a8SJulian Elischer * (whether or not we have a mailbox) as we are NEVER 1646f8132a8SJulian Elischer * going to return to the user. 1656f8132a8SJulian Elischer * The flag will not be set yet if we are exiting 1666f8132a8SJulian Elischer * because of a signal, pagefault, or similar 1676f8132a8SJulian Elischer * (or even an exit(2) from the UTS). 1686f8132a8SJulian Elischer */ 1696f8132a8SJulian Elischer td->td_flags |= TDF_UNBOUND; 170e602ba25SJulian Elischer 171e602ba25SJulian Elischer /* 172e602ba25SJulian Elischer * Kill off the other threads. This requires 173e602ba25SJulian Elischer * Some co-operation from other parts of the kernel 174e602ba25SJulian Elischer * so it may not be instant. 175e602ba25SJulian Elischer * With this state set: 176e602ba25SJulian Elischer * Any thread entering the kernel from userspace will 177e602ba25SJulian Elischer * thread_exit() in trap(). Any thread attempting to 178e602ba25SJulian Elischer * sleep will return immediatly 179e602ba25SJulian Elischer * with EINTR or EWOULDBLOCK, which will hopefully force them 180e602ba25SJulian Elischer * to back out to userland, freeing resources as they go, and 181e602ba25SJulian Elischer * anything attempting to return to userland will thread_exit() 182e602ba25SJulian Elischer * from userret(). thread_exit() will unsuspend us 183e602ba25SJulian Elischer * when the last other thread exits. 184e602ba25SJulian Elischer */ 1851279572aSDavid Xu if (thread_single(SINGLE_EXIT)) { 186e602ba25SJulian Elischer panic ("Exit: Single threading fouled up"); 187e602ba25SJulian Elischer } 188e602ba25SJulian Elischer /* 189e602ba25SJulian Elischer * All other activity in this process is now stopped. 190e602ba25SJulian Elischer * Remove excess KSEs and KSEGRPS. XXXKSE (when we have them) 191e602ba25SJulian Elischer * ... 192e602ba25SJulian Elischer * Turn off threading support. 193e602ba25SJulian Elischer */ 194e602ba25SJulian Elischer p->p_flag &= ~P_KSES; 1956f8132a8SJulian Elischer td->td_flags &= ~TDF_UNBOUND; 196e602ba25SJulian Elischer thread_single_end(); /* Don't need this any more. */ 197e602ba25SJulian Elischer } 198e602ba25SJulian Elischer /* 199e602ba25SJulian Elischer * With this state set: 200e602ba25SJulian Elischer * Any thread entering the kernel from userspace will thread_exit() 201e602ba25SJulian Elischer * in trap(). Any thread attempting to sleep will return immediatly 202e602ba25SJulian Elischer * with EINTR or EWOULDBLOCK, which will hopefully force them 203e602ba25SJulian Elischer * to back out to userland, freeing resources as they go, and 204e602ba25SJulian Elischer * anything attempting to return to userland will thread_exit() 205e602ba25SJulian Elischer * from userret(). thread_exit() will do a wakeup on p->p_numthreads 206e602ba25SJulian Elischer * if it transitions to 1. 207e602ba25SJulian Elischer */ 208e602ba25SJulian Elischer 209e602ba25SJulian Elischer p->p_flag |= P_WEXIT; 210e602ba25SJulian Elischer PROC_UNLOCK(p); 211b40ce416SJulian Elischer 2127a6b989bSJohn Baldwin /* Are we a task leader? */ 2132c1011f7SJohn Dyson if (p == p->p_leader) { 214c6544064SJohn Baldwin mtx_lock(&ppeers_lock); 2152c1011f7SJohn Dyson q = p->p_peers; 216776e0b36SJohn Baldwin while (q != NULL) { 217776e0b36SJohn Baldwin PROC_LOCK(q); 218776e0b36SJohn Baldwin psignal(q, SIGKILL); 219776e0b36SJohn Baldwin PROC_UNLOCK(q); 2202c1011f7SJohn Dyson q = q->p_peers; 2212c1011f7SJohn Dyson } 222c6544064SJohn Baldwin while (p->p_peers != NULL) 223c6544064SJohn Baldwin msleep(p, &ppeers_lock, PWAIT, "exit1", 0); 224c6544064SJohn Baldwin mtx_unlock(&ppeers_lock); 2252c1011f7SJohn Dyson } 2262c1011f7SJohn Dyson 227df8bae1dSRodney W. Grimes #ifdef PGINPROF 228df8bae1dSRodney W. Grimes vmsizmon(); 229df8bae1dSRodney W. Grimes #endif 2302a024a2bSSean Eric Fagan STOPEVENT(p, S_EXIT, rv); 23189361835SSean Eric Fagan wakeup(&p->p_stype); /* Wakeup anyone in procfs' PIOCWAIT */ 2322a024a2bSSean Eric Fagan 233fed06968SJulian Elischer /* 234e9189611SPeter Wemm * Check if any loadable modules need anything done at process exit. 235fed06968SJulian Elischer * e.g. SYSV IPC stuff 236fed06968SJulian Elischer * XXX what if one of these generates an error? 237fed06968SJulian Elischer */ 23893efcae8SPoul-Henning Kamp TAILQ_FOREACH(ep, &exit_list, next) 239fed06968SJulian Elischer (*ep->function)(p); 240fed06968SJulian Elischer 241a914fb6bSJohn Baldwin 242df8bae1dSRodney W. Grimes MALLOC(p->p_ru, struct rusage *, sizeof(struct rusage), 24344956c98SAlfred Perlstein M_ZOMBIE, 0); 244df8bae1dSRodney W. Grimes /* 245df8bae1dSRodney W. Grimes * If parent is waiting for us to exit or exec, 246df8bae1dSRodney W. Grimes * P_PPWAIT is set; we will wakeup the parent below. 247df8bae1dSRodney W. Grimes */ 248a914fb6bSJohn Baldwin PROC_LOCK(p); 249a282253aSJulian Elischer stopprofclock(p); 250df8bae1dSRodney W. Grimes p->p_flag &= ~(P_TRACED | P_PPWAIT); 2511d9c5696SJuli Mallett SIGEMPTYSET(p->p_siglist); 252a914fb6bSJohn Baldwin PROC_UNLOCK(p); 2534cf41af3SPoul-Henning Kamp if (timevalisset(&p->p_realtimer.it_value)) 2544f559836SJake Burkholder callout_stop(&p->p_itcallout); 255df8bae1dSRodney W. Grimes 256df8bae1dSRodney W. Grimes /* 257831d27a9SDon Lewis * Reset any sigio structures pointing to us as a result of 258831d27a9SDon Lewis * F_SETOWN with our pid. 259831d27a9SDon Lewis */ 260831d27a9SDon Lewis funsetownlst(&p->p_sigiolst); 261831d27a9SDon Lewis 262831d27a9SDon Lewis /* 263df8bae1dSRodney W. Grimes * Close open files and release open-file table. 264df8bae1dSRodney W. Grimes * This may block! 265df8bae1dSRodney W. Grimes */ 26612240b11SJohn Baldwin fdfree(td); /* XXXKSE *//* may not be the one in proc */ 267df8bae1dSRodney W. Grimes 268a914fb6bSJohn Baldwin /* 269a914fb6bSJohn Baldwin * Remove ourself from our leader's peer list and wake our leader. 270a914fb6bSJohn Baldwin */ 271c6544064SJohn Baldwin mtx_lock(&ppeers_lock); 27279fc0bf4SMike Smith if (p->p_leader->p_peers) { 27379fc0bf4SMike Smith q = p->p_leader; 27479fc0bf4SMike Smith while (q->p_peers != p) 27579fc0bf4SMike Smith q = q->p_peers; 27679fc0bf4SMike Smith q->p_peers = p->p_peers; 2777f05b035SAlfred Perlstein wakeup(p->p_leader); 27879fc0bf4SMike Smith } 279c6544064SJohn Baldwin mtx_unlock(&ppeers_lock); 28079fc0bf4SMike Smith 281df8bae1dSRodney W. Grimes /* The next two chunks should probably be moved to vmspace_exit. */ 282df8bae1dSRodney W. Grimes vm = p->p_vmspace; 283df8bae1dSRodney W. Grimes /* 284df8bae1dSRodney W. Grimes * Release user portion of address space. 285df8bae1dSRodney W. Grimes * This releases references to vnodes, 286df8bae1dSRodney W. Grimes * which could cause I/O if the file has been unlinked. 287df8bae1dSRodney W. Grimes * Need to do this early enough that we can still sleep. 288df8bae1dSRodney W. Grimes * Can't free the entire vmspace as the kernel stack 289df8bae1dSRodney W. Grimes * may be mapped within that space also. 290389d2b6eSMatthew Dillon * 291389d2b6eSMatthew Dillon * Processes sharing the same vmspace may exit in one order, and 292389d2b6eSMatthew Dillon * get cleaned up by vmspace_exit() in a different order. The 293389d2b6eSMatthew Dillon * last exiting process to reach this point releases as much of 294389d2b6eSMatthew Dillon * the environment as it can, and the last process cleaned up 295389d2b6eSMatthew Dillon * by vmspace_exit() (which decrements exitingcnt) cleans up the 296389d2b6eSMatthew Dillon * remainder. 297df8bae1dSRodney W. Grimes */ 298389d2b6eSMatthew Dillon ++vm->vm_exitingcnt; 299582ec34cSAlfred Perlstein if (--vm->vm_refcnt == 0) { 3003db161e0SMatthew Dillon shmexit(vm); 3012d21129dSAlan Cox vm_page_lock_queues(); 30205ba50f5SJake Burkholder pmap_remove_pages(vmspace_pmap(vm), vm_map_min(&vm->vm_map), 30305ba50f5SJake Burkholder vm_map_max(&vm->vm_map)); 3042d21129dSAlan Cox vm_page_unlock_queues(); 30505ba50f5SJake Burkholder (void) vm_map_remove(&vm->vm_map, vm_map_min(&vm->vm_map), 30605ba50f5SJake Burkholder vm_map_max(&vm->vm_map)); 3079d3fbbb5SJohn Dyson } 308df8bae1dSRodney W. Grimes 309ea97757aSJohn Baldwin sx_xlock(&proctree_lock); 310df8bae1dSRodney W. Grimes if (SESS_LEADER(p)) { 311f591779bSSeigo Tanimura register struct session *sp; 312df8bae1dSRodney W. Grimes 313f591779bSSeigo Tanimura sp = p->p_session; 314df8bae1dSRodney W. Grimes if (sp->s_ttyvp) { 315df8bae1dSRodney W. Grimes /* 316df8bae1dSRodney W. Grimes * Controlling process. 317df8bae1dSRodney W. Grimes * Signal foreground pgrp, 318df8bae1dSRodney W. Grimes * drain controlling terminal 319df8bae1dSRodney W. Grimes * and revoke access to controlling terminal. 320df8bae1dSRodney W. Grimes */ 321dd45d8adSJulian Elischer if (sp->s_ttyp && (sp->s_ttyp->t_session == sp)) { 322f591779bSSeigo Tanimura tp = sp->s_ttyp; 323f591779bSSeigo Tanimura if (sp->s_ttyp->t_pgrp) { 324f591779bSSeigo Tanimura PGRP_LOCK(sp->s_ttyp->t_pgrp); 325df8bae1dSRodney W. Grimes pgsignal(sp->s_ttyp->t_pgrp, SIGHUP, 1); 326f591779bSSeigo Tanimura PGRP_UNLOCK(sp->s_ttyp->t_pgrp); 327f591779bSSeigo Tanimura } 328f591779bSSeigo Tanimura /* XXX tp should be locked. */ 329ea97757aSJohn Baldwin sx_xunlock(&proctree_lock); 330f591779bSSeigo Tanimura (void) ttywait(tp); 331ea97757aSJohn Baldwin sx_xlock(&proctree_lock); 332df8bae1dSRodney W. Grimes /* 333df8bae1dSRodney W. Grimes * The tty could have been revoked 334df8bae1dSRodney W. Grimes * if we blocked. 335df8bae1dSRodney W. Grimes */ 336f591779bSSeigo Tanimura if (sp->s_ttyvp) { 337f591779bSSeigo Tanimura ttyvp = sp->s_ttyvp; 338f591779bSSeigo Tanimura SESS_LOCK(p->p_session); 339df8bae1dSRodney W. Grimes sp->s_ttyvp = NULL; 340f591779bSSeigo Tanimura SESS_UNLOCK(p->p_session); 341ea97757aSJohn Baldwin sx_xunlock(&proctree_lock); 342f591779bSSeigo Tanimura VOP_REVOKE(ttyvp, REVOKEALL); 343f591779bSSeigo Tanimura vrele(ttyvp); 344ea97757aSJohn Baldwin sx_xlock(&proctree_lock); 345f591779bSSeigo Tanimura } 346f591779bSSeigo Tanimura } 347f591779bSSeigo Tanimura if (sp->s_ttyvp) { 348f591779bSSeigo Tanimura ttyvp = sp->s_ttyvp; 349f591779bSSeigo Tanimura SESS_LOCK(p->p_session); 350f591779bSSeigo Tanimura sp->s_ttyvp = NULL; 351f591779bSSeigo Tanimura SESS_UNLOCK(p->p_session); 352f591779bSSeigo Tanimura vrele(ttyvp); 353f591779bSSeigo Tanimura } 354df8bae1dSRodney W. Grimes /* 355df8bae1dSRodney W. Grimes * s_ttyp is not zero'd; we use this to indicate 356df8bae1dSRodney W. Grimes * that the session once had a controlling terminal. 357df8bae1dSRodney W. Grimes * (for logging and informational purposes) 358df8bae1dSRodney W. Grimes */ 359df8bae1dSRodney W. Grimes } 360f591779bSSeigo Tanimura SESS_LOCK(p->p_session); 361df8bae1dSRodney W. Grimes sp->s_leader = NULL; 362f591779bSSeigo Tanimura SESS_UNLOCK(p->p_session); 363f591779bSSeigo Tanimura } 364df8bae1dSRodney W. Grimes fixjobc(p, p->p_pgrp, 0); 365ea97757aSJohn Baldwin sx_xunlock(&proctree_lock); 366b40ce416SJulian Elischer (void)acct_process(td); 367df8bae1dSRodney W. Grimes #ifdef KTRACE 368df8bae1dSRodney W. Grimes /* 369df8bae1dSRodney W. Grimes * release trace file 370df8bae1dSRodney W. Grimes */ 371d7aadbf9SJohn Baldwin PROC_LOCK(p); 3726c84de02SJohn Baldwin mtx_lock(&ktrace_mtx); 373df8bae1dSRodney W. Grimes p->p_traceflag = 0; /* don't trace the vrele() */ 374d7aadbf9SJohn Baldwin tracevp = p->p_tracep; 37579deba82SMatthew Dillon p->p_tracep = NULL; 3766c84de02SJohn Baldwin mtx_unlock(&ktrace_mtx); 377d7aadbf9SJohn Baldwin PROC_UNLOCK(p); 378d7aadbf9SJohn Baldwin if (tracevp != NULL) 379d7aadbf9SJohn Baldwin vrele(tracevp); 380df8bae1dSRodney W. Grimes #endif 381df8bae1dSRodney W. Grimes /* 382ee42d0a9SDavid Malone * Release reference to text vnode 383ee42d0a9SDavid Malone */ 384ee42d0a9SDavid Malone if ((vtmp = p->p_textvp) != NULL) { 385ee42d0a9SDavid Malone p->p_textvp = NULL; 386ee42d0a9SDavid Malone vrele(vtmp); 387ee42d0a9SDavid Malone } 388ee42d0a9SDavid Malone 389ee42d0a9SDavid Malone /* 390d7aadbf9SJohn Baldwin * Release our limits structure. 391d7aadbf9SJohn Baldwin */ 392d7aadbf9SJohn Baldwin mtx_assert(&Giant, MA_OWNED); 393d7aadbf9SJohn Baldwin if (--p->p_limit->p_refcnt == 0) { 394d7aadbf9SJohn Baldwin FREE(p->p_limit, M_SUBPROC); 395d7aadbf9SJohn Baldwin p->p_limit = NULL; 396d7aadbf9SJohn Baldwin } 397d7aadbf9SJohn Baldwin 398d7aadbf9SJohn Baldwin /* 399d7aadbf9SJohn Baldwin * Release this thread's reference to the ucred. The actual proc 400d7aadbf9SJohn Baldwin * reference will stay around until the proc is harvested by 401d7aadbf9SJohn Baldwin * wait(). At this point the ucred is immutable (no other threads 402d7aadbf9SJohn Baldwin * from this proc are around that can change it) so we leave the 403d7aadbf9SJohn Baldwin * per-thread ucred pointer intact in case it is needed although 404d7aadbf9SJohn Baldwin * in theory nothing should be using it at this point. 405d7aadbf9SJohn Baldwin */ 406d7aadbf9SJohn Baldwin crfree(td->td_ucred); 407d7aadbf9SJohn Baldwin 408d7aadbf9SJohn Baldwin /* 409df8bae1dSRodney W. Grimes * Remove proc from allproc queue and pidhash chain. 410df8bae1dSRodney W. Grimes * Place onto zombproc. Unlink from parent's child list. 411df8bae1dSRodney W. Grimes */ 4121005a129SJohn Baldwin sx_xlock(&allproc_lock); 413b75356e1SJeffrey Hsu LIST_REMOVE(p, p_list); 414b75356e1SJeffrey Hsu LIST_INSERT_HEAD(&zombproc, p, p_list); 415b75356e1SJeffrey Hsu LIST_REMOVE(p, p_hash); 4161005a129SJohn Baldwin sx_xunlock(&allproc_lock); 417df8bae1dSRodney W. Grimes 4181005a129SJohn Baldwin sx_xlock(&proctree_lock); 4192e3c8fcbSPoul-Henning Kamp q = LIST_FIRST(&p->p_children); 420a914fb6bSJohn Baldwin if (q != NULL) /* only need this if any child is S_ZOMB */ 4217f05b035SAlfred Perlstein wakeup(initproc); 422a914fb6bSJohn Baldwin for (; q != NULL; q = nq) { 4232e3c8fcbSPoul-Henning Kamp nq = LIST_NEXT(q, p_sibling); 424a914fb6bSJohn Baldwin PROC_LOCK(q); 425c65437a3SJohn Baldwin proc_reparent(q, initproc); 4264ac9ae70SJulian Elischer q->p_sigparent = SIGCHLD; 427df8bae1dSRodney W. Grimes /* 428df8bae1dSRodney W. Grimes * Traced processes are killed 429df8bae1dSRodney W. Grimes * since their existence means someone is screwing up. 430df8bae1dSRodney W. Grimes */ 431df8bae1dSRodney W. Grimes if (q->p_flag & P_TRACED) { 432df8bae1dSRodney W. Grimes q->p_flag &= ~P_TRACED; 433df8bae1dSRodney W. Grimes psignal(q, SIGKILL); 434c65437a3SJohn Baldwin } 435a914fb6bSJohn Baldwin PROC_UNLOCK(q); 436df8bae1dSRodney W. Grimes } 437df8bae1dSRodney W. Grimes 438df8bae1dSRodney W. Grimes /* 439df8bae1dSRodney W. Grimes * Save exit status and final rusage info, adding in child rusage 440df8bae1dSRodney W. Grimes * info and self times. 441df8bae1dSRodney W. Grimes */ 442d7aadbf9SJohn Baldwin PROC_LOCK(p); 443df8bae1dSRodney W. Grimes p->p_xstat = rv; 444df8bae1dSRodney W. Grimes *p->p_ru = p->p_stats->p_ru; 4459ed346baSBosko Milekic mtx_lock_spin(&sched_lock); 446df8bae1dSRodney W. Grimes calcru(p, &p->p_ru->ru_utime, &p->p_ru->ru_stime, NULL); 4479ed346baSBosko Milekic mtx_unlock_spin(&sched_lock); 448df8bae1dSRodney W. Grimes ruadd(p->p_ru, &p->p_stats->p_cru); 449df8bae1dSRodney W. Grimes 450df8bae1dSRodney W. Grimes /* 4517a6b989bSJohn Baldwin * Notify interested parties of our demise. 452cb679c38SJonathan Lemon */ 453a274d19bSBrian Feldman KNOTE(&p->p_klist, NOTE_EXIT); 454cb679c38SJonathan Lemon 455cb679c38SJonathan Lemon /* 456645682fdSLuoqi Chen * Notify parent that we're gone. If parent has the PS_NOCLDWAIT 457ba1551caSIan Dowse * flag set, or if the handler is set to SIG_IGN, notify process 458ba1551caSIan Dowse * 1 instead (and hope it will handle this situation). 459df8bae1dSRodney W. Grimes */ 460d7aadbf9SJohn Baldwin PROC_LOCK(p->p_pptr); 461ba1551caSIan Dowse if (p->p_pptr->p_procsig->ps_flag & (PS_NOCLDWAIT | PS_CLDSIGIGN)) { 462276c5169SJohn Baldwin struct proc *pp; 463276c5169SJohn Baldwin 464276c5169SJohn Baldwin pp = p->p_pptr; 465f591779bSSeigo Tanimura PROC_UNLOCK(pp); 466245f17d4SJoerg Wunsch proc_reparent(p, initproc); 467f591779bSSeigo Tanimura PROC_LOCK(p->p_pptr); 468245f17d4SJoerg Wunsch /* 469245f17d4SJoerg Wunsch * If this was the last child of our parent, notify 470245f17d4SJoerg Wunsch * parent, so in case he was wait(2)ing, he will 471245f17d4SJoerg Wunsch * continue. 472245f17d4SJoerg Wunsch */ 473245f17d4SJoerg Wunsch if (LIST_EMPTY(&pp->p_children)) 4747f05b035SAlfred Perlstein wakeup(pp); 475245f17d4SJoerg Wunsch } 476245f17d4SJoerg Wunsch 477c65437a3SJohn Baldwin if (p->p_sigparent && p->p_pptr != initproc) 4786626c604SJulian Elischer psignal(p->p_pptr, p->p_sigparent); 479c65437a3SJohn Baldwin else 4806626c604SJulian Elischer psignal(p->p_pptr, SIGCHLD); 481c65437a3SJohn Baldwin PROC_UNLOCK(p->p_pptr); 482776e0b36SJohn Baldwin 483776e0b36SJohn Baldwin /* 484776e0b36SJohn Baldwin * If this is a kthread, then wakeup anyone waiting for it to exit. 485776e0b36SJohn Baldwin */ 486776e0b36SJohn Baldwin if (p->p_flag & P_KTHREAD) 4877f05b035SAlfred Perlstein wakeup(p); 488c65437a3SJohn Baldwin PROC_UNLOCK(p); 4898e2e767bSJohn Baldwin 4908e2e767bSJohn Baldwin /* 491df8bae1dSRodney W. Grimes * Finally, call machine-dependent code to release the remaining 492696058c3SJulian Elischer * resources including address space. 493582ec34cSAlfred Perlstein * The address space is released by "vmspace_exitfree(p)" in 494582ec34cSAlfred Perlstein * vm_waitproc(). 495df8bae1dSRodney W. Grimes */ 496b40ce416SJulian Elischer cpu_exit(td); 497eb30c1c0SPeter Wemm 498eb30c1c0SPeter Wemm PROC_LOCK(p); 499d7aadbf9SJohn Baldwin PROC_LOCK(p->p_pptr); 500d7aadbf9SJohn Baldwin sx_xunlock(&proctree_lock); 501eb30c1c0SPeter Wemm mtx_lock_spin(&sched_lock); 502696058c3SJulian Elischer 503eb30c1c0SPeter Wemm while (mtx_owned(&Giant)) 504c86b6ff5SJohn Baldwin mtx_unlock(&Giant); 505eb30c1c0SPeter Wemm 506eb30c1c0SPeter Wemm /* 507eb30c1c0SPeter Wemm * We have to wait until after releasing all locks before 508e602ba25SJulian Elischer * changing p_state. If we block on a mutex then we will be 509eb30c1c0SPeter Wemm * back at SRUN when we resume and our parent will never 510eb30c1c0SPeter Wemm * harvest us. 511eb30c1c0SPeter Wemm */ 512e602ba25SJulian Elischer p->p_state = PRS_ZOMBIE; 513eb30c1c0SPeter Wemm 514eb30c1c0SPeter Wemm wakeup(p->p_pptr); 515d7aadbf9SJohn Baldwin PROC_UNLOCK(p->p_pptr); 516eb30c1c0SPeter Wemm cnt.v_swtch++; 517d7aadbf9SJohn Baldwin binuptime(PCPU_PTR(switchtime)); 518d7aadbf9SJohn Baldwin PCPU_SET(switchticks, ticks); 519d7aadbf9SJohn Baldwin 520e602ba25SJulian Elischer cpu_sched_exit(td); /* XXXKSE check if this should be in thread_exit */ 521e602ba25SJulian Elischer /* 522696058c3SJulian Elischer * Make sure the scheduler takes this thread out of its tables etc. 523e602ba25SJulian Elischer * This will also release this thread's reference to the ucred. 524696058c3SJulian Elischer * Other thread parts to release include pcb bits and such. 525e602ba25SJulian Elischer */ 526e602ba25SJulian Elischer thread_exit(); 527df8bae1dSRodney W. Grimes } 528df8bae1dSRodney W. Grimes 529b2f9e8b1SBruce Evans #ifdef COMPAT_43 530234216efSMatthew Dillon /* 5317a6b989bSJohn Baldwin * MPSAFE. The dirty work is handled by wait1(). 532234216efSMatthew Dillon */ 53326f9a767SRodney W. Grimes int 534b40ce416SJulian Elischer owait(td, uap) 535b40ce416SJulian Elischer struct thread *td; 5365fdb8324SBruce Evans register struct owait_args /* { 5375fdb8324SBruce Evans int dummy; 5385fdb8324SBruce Evans } */ *uap; 539df8bae1dSRodney W. Grimes { 54093c9414eSSteven Wallace struct wait_args w; 541df8bae1dSRodney W. Grimes 54293c9414eSSteven Wallace w.options = 0; 54393c9414eSSteven Wallace w.rusage = NULL; 54493c9414eSSteven Wallace w.pid = WAIT_ANY; 54593c9414eSSteven Wallace w.status = NULL; 546b40ce416SJulian Elischer return (wait1(td, &w, 1)); 547df8bae1dSRodney W. Grimes } 548b2f9e8b1SBruce Evans #endif /* COMPAT_43 */ 549df8bae1dSRodney W. Grimes 550234216efSMatthew Dillon /* 5517a6b989bSJohn Baldwin * MPSAFE. The dirty work is handled by wait1(). 552234216efSMatthew Dillon */ 55326f9a767SRodney W. Grimes int 554b40ce416SJulian Elischer wait4(td, uap) 555b40ce416SJulian Elischer struct thread *td; 556df8bae1dSRodney W. Grimes struct wait_args *uap; 557df8bae1dSRodney W. Grimes { 558b40ce416SJulian Elischer 559b40ce416SJulian Elischer return (wait1(td, uap, 0)); 560df8bae1dSRodney W. Grimes } 561df8bae1dSRodney W. Grimes 562234216efSMatthew Dillon /* 563234216efSMatthew Dillon * MPSAFE 564234216efSMatthew Dillon */ 56593c9414eSSteven Wallace static int 566b40ce416SJulian Elischer wait1(td, uap, compat) 567b40ce416SJulian Elischer register struct thread *td; 5685fdb8324SBruce Evans register struct wait_args /* { 5695fdb8324SBruce Evans int pid; 5705fdb8324SBruce Evans int *status; 5715fdb8324SBruce Evans int options; 5725fdb8324SBruce Evans struct rusage *rusage; 5735fdb8324SBruce Evans } */ *uap; 57493c9414eSSteven Wallace int compat; 575df8bae1dSRodney W. Grimes { 576276c5169SJohn Baldwin struct rusage ru; 57748bfcdddSJulian Elischer int nfound; 57848bfcdddSJulian Elischer struct proc *p, *q, *t; 579f23c6d68SSteven Wallace int status, error; 580df8bae1dSRodney W. Grimes 581b40ce416SJulian Elischer q = td->td_proc; 582f591779bSSeigo Tanimura if (uap->pid == 0) { 583f591779bSSeigo Tanimura PROC_LOCK(q); 584df8bae1dSRodney W. Grimes uap->pid = -q->p_pgid; 585f591779bSSeigo Tanimura PROC_UNLOCK(q); 586f591779bSSeigo Tanimura } 5876ee093fbSMike Barcroft if (uap->options &~ (WUNTRACED|WNOHANG|WCONTINUED|WLINUXCLONE)) 5886dc958b9SJohn Baldwin return (EINVAL); 5896dc958b9SJohn Baldwin mtx_lock(&Giant); 590df8bae1dSRodney W. Grimes loop: 591df8bae1dSRodney W. Grimes nfound = 0; 592d7aadbf9SJohn Baldwin sx_xlock(&proctree_lock); 5932e3c8fcbSPoul-Henning Kamp LIST_FOREACH(p, &q->p_children, p_sibling) { 594f591779bSSeigo Tanimura PROC_LOCK(p); 595df8bae1dSRodney W. Grimes if (uap->pid != WAIT_ANY && 596f591779bSSeigo Tanimura p->p_pid != uap->pid && p->p_pgid != -uap->pid) { 597f591779bSSeigo Tanimura PROC_UNLOCK(p); 598df8bae1dSRodney W. Grimes continue; 599f591779bSSeigo Tanimura } 6004ac9ae70SJulian Elischer 6011156bc4dSJake Burkholder /* 6021156bc4dSJake Burkholder * This special case handles a kthread spawned by linux_clone 6031156bc4dSJake Burkholder * (see linux_misc.c). The linux_wait4 and linux_waitpid 6041156bc4dSJake Burkholder * functions need to be able to distinguish between waiting 6051156bc4dSJake Burkholder * on a process and waiting on a thread. It is a thread if 6061156bc4dSJake Burkholder * p_sigparent is not SIGCHLD, and the WLINUXCLONE option 6071156bc4dSJake Burkholder * signifies we want to wait for threads and not processes. 6084ac9ae70SJulian Elischer */ 6091156bc4dSJake Burkholder if ((p->p_sigparent != SIGCHLD) ^ 610a914fb6bSJohn Baldwin ((uap->options & WLINUXCLONE) != 0)) { 611a914fb6bSJohn Baldwin PROC_UNLOCK(p); 6124ac9ae70SJulian Elischer continue; 613a914fb6bSJohn Baldwin } 6144ac9ae70SJulian Elischer 615df8bae1dSRodney W. Grimes nfound++; 616e602ba25SJulian Elischer if (p->p_state == PRS_ZOMBIE) { 617b40ce416SJulian Elischer /* 618b43179fbSJeff Roberson * Allow the scheduler to adjust the priority of the 619b43179fbSJeff Roberson * parent when a kseg is exiting. 620b40ce416SJulian Elischer */ 621b40ce416SJulian Elischer if (curthread->td_proc->p_pid != 1) { 622d7aadbf9SJohn Baldwin mtx_lock_spin(&sched_lock); 623b43179fbSJeff Roberson sched_exit(curthread->td_ksegrp, 624b43179fbSJeff Roberson FIRST_KSEGRP_IN_PROC(p)); 625c65437a3SJohn Baldwin mtx_unlock_spin(&sched_lock); 626d7aadbf9SJohn Baldwin } 627c65437a3SJohn Baldwin 628b40ce416SJulian Elischer td->td_retval[0] = p->p_pid; 629b2f9e8b1SBruce Evans #ifdef COMPAT_43 63093c9414eSSteven Wallace if (compat) 631b40ce416SJulian Elischer td->td_retval[1] = p->p_xstat; 632df8bae1dSRodney W. Grimes else 633df8bae1dSRodney W. Grimes #endif 634df8bae1dSRodney W. Grimes if (uap->status) { 635df8bae1dSRodney W. Grimes status = p->p_xstat; /* convert to int */ 636d7aadbf9SJohn Baldwin PROC_UNLOCK(p); 6377f05b035SAlfred Perlstein if ((error = copyout(&status, 6387f05b035SAlfred Perlstein uap->status, sizeof(status)))) { 639d7aadbf9SJohn Baldwin sx_xunlock(&proctree_lock); 640d7aadbf9SJohn Baldwin mtx_unlock(&Giant); 641d7aadbf9SJohn Baldwin return (error); 642234216efSMatthew Dillon } 643d7aadbf9SJohn Baldwin PROC_LOCK(p); 644df8bae1dSRodney W. Grimes } 645d7aadbf9SJohn Baldwin if (uap->rusage) { 646d7aadbf9SJohn Baldwin bcopy(p->p_ru, &ru, sizeof(ru)); 647d7aadbf9SJohn Baldwin PROC_UNLOCK(p); 6487f05b035SAlfred Perlstein if ((error = copyout(&ru, 6497f05b035SAlfred Perlstein uap->rusage, sizeof (struct rusage)))) { 650d7aadbf9SJohn Baldwin sx_xunlock(&proctree_lock); 651d7aadbf9SJohn Baldwin mtx_unlock(&Giant); 652d7aadbf9SJohn Baldwin return (error); 653234216efSMatthew Dillon } 654d7aadbf9SJohn Baldwin } else 655d7aadbf9SJohn Baldwin PROC_UNLOCK(p); 656df8bae1dSRodney W. Grimes /* 657df8bae1dSRodney W. Grimes * If we got the child via a ptrace 'attach', 658df8bae1dSRodney W. Grimes * we need to give it back to the old parent. 659df8bae1dSRodney W. Grimes */ 660d7aadbf9SJohn Baldwin if (p->p_oppid && (t = pfind(p->p_oppid)) != NULL) { 661c65437a3SJohn Baldwin PROC_LOCK(p); 662df8bae1dSRodney W. Grimes p->p_oppid = 0; 663df8bae1dSRodney W. Grimes proc_reparent(p, t); 664c65437a3SJohn Baldwin PROC_UNLOCK(p); 665df8bae1dSRodney W. Grimes psignal(t, SIGCHLD); 6667f05b035SAlfred Perlstein wakeup(t); 667c65437a3SJohn Baldwin PROC_UNLOCK(t); 6681005a129SJohn Baldwin sx_xunlock(&proctree_lock); 669d7aadbf9SJohn Baldwin mtx_unlock(&Giant); 670d7aadbf9SJohn Baldwin return (0); 671df8bae1dSRodney W. Grimes } 672df8bae1dSRodney W. Grimes /* 673d7aadbf9SJohn Baldwin * Remove other references to this process to ensure 674d7aadbf9SJohn Baldwin * we have an exclusive reference. 675df8bae1dSRodney W. Grimes */ 676ebdc3f1dSSeigo Tanimura leavepgrp(p); 677ebdc3f1dSSeigo Tanimura 678ebdc3f1dSSeigo Tanimura sx_xlock(&allproc_lock); 679ebdc3f1dSSeigo Tanimura LIST_REMOVE(p, p_list); /* off zombproc */ 680ebdc3f1dSSeigo Tanimura sx_xunlock(&allproc_lock); 681ebdc3f1dSSeigo Tanimura 682ebdc3f1dSSeigo Tanimura LIST_REMOVE(p, p_sibling); 683ebdc3f1dSSeigo Tanimura sx_xunlock(&proctree_lock); 684ebdc3f1dSSeigo Tanimura 685ebdc3f1dSSeigo Tanimura /* 686d7aadbf9SJohn Baldwin * As a side effect of this lock, we know that 687d7aadbf9SJohn Baldwin * all other writes to this proc are visible now, so 688d7aadbf9SJohn Baldwin * no more locking is needed for p. 689d7aadbf9SJohn Baldwin */ 690d7aadbf9SJohn Baldwin PROC_LOCK(p); 691d7aadbf9SJohn Baldwin p->p_xstat = 0; /* XXX: why? */ 692d7aadbf9SJohn Baldwin PROC_UNLOCK(p); 693d7aadbf9SJohn Baldwin PROC_LOCK(q); 694d7aadbf9SJohn Baldwin ruadd(&q->p_stats->p_cru, p->p_ru); 695d7aadbf9SJohn Baldwin PROC_UNLOCK(q); 696d7aadbf9SJohn Baldwin FREE(p->p_ru, M_ZOMBIE); 697d7aadbf9SJohn Baldwin p->p_ru = NULL; 698d7aadbf9SJohn Baldwin 699d7aadbf9SJohn Baldwin /* 700d7aadbf9SJohn Baldwin * Decrement the count of procs running with this uid. 701d7aadbf9SJohn Baldwin */ 702d7aadbf9SJohn Baldwin (void)chgproccnt(p->p_ucred->cr_ruidinfo, -1, 0); 703d7aadbf9SJohn Baldwin 704d7aadbf9SJohn Baldwin /* 705df8bae1dSRodney W. Grimes * Free up credentials. 706df8bae1dSRodney W. Grimes */ 707da654d90SPoul-Henning Kamp crfree(p->p_ucred); 708d7aadbf9SJohn Baldwin p->p_ucred = NULL; /* XXX: why? */ 709df8bae1dSRodney W. Grimes 710df8bae1dSRodney W. Grimes /* 711b9df5231SPoul-Henning Kamp * Remove unused arguments 712b9df5231SPoul-Henning Kamp */ 713d7aadbf9SJohn Baldwin pargs_drop(p->p_args); 714d7aadbf9SJohn Baldwin p->p_args = NULL; 715b9df5231SPoul-Henning Kamp 7166626c604SJulian Elischer if (--p->p_procsig->ps_refcnt == 0) { 717b40ce416SJulian Elischer if (p->p_sigacts != &p->p_uarea->u_sigacts) 718dc9c271aSJulian Elischer FREE(p->p_sigacts, M_SUBPROC); 719dc9c271aSJulian Elischer FREE(p->p_procsig, M_SUBPROC); 7206626c604SJulian Elischer p->p_procsig = NULL; 7216626c604SJulian Elischer } 72288c5ea45SJulian Elischer 723df8bae1dSRodney W. Grimes /* 724696058c3SJulian Elischer * do any thread-system specific cleanups 725e602ba25SJulian Elischer */ 726696058c3SJulian Elischer thread_wait(p); 727e602ba25SJulian Elischer 728e602ba25SJulian Elischer /* 729eb30c1c0SPeter Wemm * Give vm and machine-dependent layer a chance 730df8bae1dSRodney W. Grimes * to free anything that cpu_exit couldn't 731df8bae1dSRodney W. Grimes * release while still running in process context. 732df8bae1dSRodney W. Grimes */ 733eb30c1c0SPeter Wemm vm_waitproc(p); 7344971f62aSJohn Baldwin mtx_destroy(&p->p_mtx); 7352555374cSRobert Watson #ifdef MAC 7362555374cSRobert Watson mac_destroy_proc(p); 7372555374cSRobert Watson #endif 7381faf202eSJulian Elischer KASSERT(FIRST_THREAD_IN_PROC(p), 7391faf202eSJulian Elischer ("wait1: no residual thread!")); 740c897b813SJeff Roberson uma_zfree(proc_zone, p); 741d7aadbf9SJohn Baldwin sx_xlock(&allproc_lock); 742df8bae1dSRodney W. Grimes nprocs--; 743d7aadbf9SJohn Baldwin sx_xunlock(&allproc_lock); 744d7aadbf9SJohn Baldwin mtx_unlock(&Giant); 745d7aadbf9SJohn Baldwin return (0); 746df8bae1dSRodney W. Grimes } 747e602ba25SJulian Elischer if (P_SHOULDSTOP(p) && ((p->p_flag & P_WAITED) == 0) && 748df8bae1dSRodney W. Grimes (p->p_flag & P_TRACED || uap->options & WUNTRACED)) { 749df8bae1dSRodney W. Grimes p->p_flag |= P_WAITED; 750d7aadbf9SJohn Baldwin sx_xunlock(&proctree_lock); 751b40ce416SJulian Elischer td->td_retval[0] = p->p_pid; 752b2f9e8b1SBruce Evans #ifdef COMPAT_43 75393c9414eSSteven Wallace if (compat) { 754b40ce416SJulian Elischer td->td_retval[1] = W_STOPCODE(p->p_xstat); 755d7aadbf9SJohn Baldwin PROC_UNLOCK(p); 756df8bae1dSRodney W. Grimes error = 0; 757df8bae1dSRodney W. Grimes } else 758df8bae1dSRodney W. Grimes #endif 759df8bae1dSRodney W. Grimes if (uap->status) { 760df8bae1dSRodney W. Grimes status = W_STOPCODE(p->p_xstat); 761d7aadbf9SJohn Baldwin PROC_UNLOCK(p); 7627f05b035SAlfred Perlstein error = copyout(&status, 7637f05b035SAlfred Perlstein uap->status, sizeof(status)); 764d7aadbf9SJohn Baldwin } else { 765a914fb6bSJohn Baldwin PROC_UNLOCK(p); 766234216efSMatthew Dillon error = 0; 767df8bae1dSRodney W. Grimes } 768234216efSMatthew Dillon mtx_unlock(&Giant); 769234216efSMatthew Dillon return (error); 770df8bae1dSRodney W. Grimes } 7716ee093fbSMike Barcroft if (uap->options & WCONTINUED && (p->p_flag & P_CONTINUED)) { 7726ee093fbSMike Barcroft sx_xunlock(&proctree_lock); 7736ee093fbSMike Barcroft td->td_retval[0] = p->p_pid; 7746ee093fbSMike Barcroft p->p_flag &= ~P_CONTINUED; 7756ee093fbSMike Barcroft PROC_UNLOCK(p); 7766ee093fbSMike Barcroft 7776ee093fbSMike Barcroft if (uap->status) { 7786ee093fbSMike Barcroft status = SIGCONT; 7797f05b035SAlfred Perlstein error = copyout(&status, 7807f05b035SAlfred Perlstein uap->status, sizeof(status)); 7816ee093fbSMike Barcroft } else 7826ee093fbSMike Barcroft error = 0; 7836ee093fbSMike Barcroft 7846ee093fbSMike Barcroft mtx_unlock(&Giant); 7856ee093fbSMike Barcroft return (error); 7866ee093fbSMike Barcroft } 787d7aadbf9SJohn Baldwin PROC_UNLOCK(p); 788d7aadbf9SJohn Baldwin } 789d7aadbf9SJohn Baldwin if (nfound == 0) { 790d7aadbf9SJohn Baldwin sx_xunlock(&proctree_lock); 791d7aadbf9SJohn Baldwin mtx_unlock(&Giant); 792d7aadbf9SJohn Baldwin return (ECHILD); 793d7aadbf9SJohn Baldwin } 794d7aadbf9SJohn Baldwin if (uap->options & WNOHANG) { 795d7aadbf9SJohn Baldwin sx_xunlock(&proctree_lock); 796d7aadbf9SJohn Baldwin td->td_retval[0] = 0; 797d7aadbf9SJohn Baldwin mtx_unlock(&Giant); 798d7aadbf9SJohn Baldwin return (0); 799d7aadbf9SJohn Baldwin } 800d7aadbf9SJohn Baldwin PROC_LOCK(q); 801d7aadbf9SJohn Baldwin sx_xunlock(&proctree_lock); 8027f05b035SAlfred Perlstein error = msleep(q, &q->p_mtx, PWAIT | PCATCH, "wait", 0); 803d7aadbf9SJohn Baldwin PROC_UNLOCK(q); 804d7aadbf9SJohn Baldwin if (error) { 805d7aadbf9SJohn Baldwin mtx_unlock(&Giant); 806d7aadbf9SJohn Baldwin return (error); 807d7aadbf9SJohn Baldwin } 808d7aadbf9SJohn Baldwin goto loop; 809d7aadbf9SJohn Baldwin } 810df8bae1dSRodney W. Grimes 811df8bae1dSRodney W. Grimes /* 81298f03f90SJake Burkholder * Make process 'parent' the new parent of process 'child'. 81398f03f90SJake Burkholder * Must be called with an exclusive hold of proctree lock. 814df8bae1dSRodney W. Grimes */ 815df8bae1dSRodney W. Grimes void 816df8bae1dSRodney W. Grimes proc_reparent(child, parent) 817df8bae1dSRodney W. Grimes register struct proc *child; 818df8bae1dSRodney W. Grimes register struct proc *parent; 819df8bae1dSRodney W. Grimes { 820df8bae1dSRodney W. Grimes 8214e5e677bSJohn Baldwin sx_assert(&proctree_lock, SX_XLOCKED); 822c65437a3SJohn Baldwin PROC_LOCK_ASSERT(child, MA_OWNED); 823df8bae1dSRodney W. Grimes if (child->p_pptr == parent) 824df8bae1dSRodney W. Grimes return; 825df8bae1dSRodney W. Grimes 826b75356e1SJeffrey Hsu LIST_REMOVE(child, p_sibling); 827b75356e1SJeffrey Hsu LIST_INSERT_HEAD(&parent->p_children, child, p_sibling); 828df8bae1dSRodney W. Grimes child->p_pptr = parent; 829df8bae1dSRodney W. Grimes } 830fed06968SJulian Elischer 831e0d898b4SJulian Elischer /* 832e0d898b4SJulian Elischer * The next two functions are to handle adding/deleting items on the 833fed06968SJulian Elischer * exit callout list 834e0d898b4SJulian Elischer * 835e0d898b4SJulian Elischer * at_exit(): 836e0d898b4SJulian Elischer * Take the arguments given and put them onto the exit callout list, 837fed06968SJulian Elischer * However first make sure that it's not already there. 838fed06968SJulian Elischer * returns 0 on success. 839fed06968SJulian Elischer */ 84093efcae8SPoul-Henning Kamp 841fed06968SJulian Elischer int 842eb776aeaSBruce Evans at_exit(function) 843eb776aeaSBruce Evans exitlist_fn function; 844fed06968SJulian Elischer { 84593efcae8SPoul-Henning Kamp struct exitlist *ep; 846e0d898b4SJulian Elischer 84793efcae8SPoul-Henning Kamp #ifdef INVARIANTS 848e0d898b4SJulian Elischer /* Be noisy if the programmer has lost track of things */ 849e0d898b4SJulian Elischer if (rm_at_exit(function)) 85093efcae8SPoul-Henning Kamp printf("WARNING: exit callout entry (%p) already present\n", 85193efcae8SPoul-Henning Kamp function); 85293efcae8SPoul-Henning Kamp #endif 85393efcae8SPoul-Henning Kamp ep = malloc(sizeof(*ep), M_ATEXIT, M_NOWAIT); 854e0d898b4SJulian Elischer if (ep == NULL) 855e0d898b4SJulian Elischer return (ENOMEM); 856fed06968SJulian Elischer ep->function = function; 85793efcae8SPoul-Henning Kamp TAILQ_INSERT_TAIL(&exit_list, ep, next); 858e0d898b4SJulian Elischer return (0); 859fed06968SJulian Elischer } 86093efcae8SPoul-Henning Kamp 861fed06968SJulian Elischer /* 86293efcae8SPoul-Henning Kamp * Scan the exit callout list for the given item and remove it. 86393efcae8SPoul-Henning Kamp * Returns the number of items removed (0 or 1) 864fed06968SJulian Elischer */ 865fed06968SJulian Elischer int 866eb776aeaSBruce Evans rm_at_exit(function) 867eb776aeaSBruce Evans exitlist_fn function; 868fed06968SJulian Elischer { 86993efcae8SPoul-Henning Kamp struct exitlist *ep; 870fed06968SJulian Elischer 87193efcae8SPoul-Henning Kamp TAILQ_FOREACH(ep, &exit_list, next) { 872fed06968SJulian Elischer if (ep->function == function) { 87393efcae8SPoul-Henning Kamp TAILQ_REMOVE(&exit_list, ep, next); 87493efcae8SPoul-Henning Kamp free(ep, M_ATEXIT); 87593efcae8SPoul-Henning Kamp return (1); 876fed06968SJulian Elischer } 877fed06968SJulian Elischer } 87893efcae8SPoul-Henning Kamp return (0); 879fed06968SJulian Elischer } 880