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" 44db6a20e2SGarrett Wollman 45df8bae1dSRodney W. Grimes #include <sys/param.h> 46df8bae1dSRodney W. Grimes #include <sys/systm.h> 475fdb8324SBruce Evans #include <sys/sysproto.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> 532a024a2bSSean Eric Fagan #include <sys/pioctl.h> 54df8bae1dSRodney W. Grimes #include <sys/tty.h> 55df8bae1dSRodney W. Grimes #include <sys/wait.h> 56df8bae1dSRodney W. Grimes #include <sys/vnode.h> 57df8bae1dSRodney W. Grimes #include <sys/resourcevar.h> 58797f2d22SPoul-Henning Kamp #include <sys/signalvar.h> 591005a129SJohn Baldwin #include <sys/sx.h> 60df8bae1dSRodney W. Grimes #include <sys/ptrace.h> 617c409b8aSJeffrey Hsu #include <sys/acct.h> /* for acct_process() function prototype */ 62797f2d22SPoul-Henning Kamp #include <sys/filedesc.h> 63780dc5a8SPeter Wemm #include <sys/shm.h> 64780dc5a8SPeter Wemm #include <sys/sem.h> 655aaef07cSJohn Dyson #include <sys/aio.h> 6675c13541SPoul-Henning Kamp #include <sys/jail.h> 67780dc5a8SPeter Wemm 68df8bae1dSRodney W. Grimes #include <vm/vm.h> 69efeaf95aSDavid Greenman #include <vm/vm_param.h> 70efeaf95aSDavid Greenman #include <vm/pmap.h> 71efeaf95aSDavid Greenman #include <vm/vm_map.h> 722d8acc0fSJohn Dyson #include <vm/vm_zone.h> 73dc9c271aSJulian Elischer #include <sys/user.h> 74df8bae1dSRodney W. Grimes 75ba198b1cSMark Newton /* Required to be non-static for SysVR4 emulator */ 7669a6f20bSMark Newton MALLOC_DEFINE(M_ZOMBIE, "zombie", "zombie proc status"); 7755166637SPoul-Henning Kamp 7893efcae8SPoul-Henning Kamp static MALLOC_DEFINE(M_ATEXIT, "atexit", "atexit callback"); 7993efcae8SPoul-Henning Kamp 8001166e92SBruce Evans static int wait1 __P((struct proc *, struct wait_args *, int)); 815fdb8324SBruce Evans 82df8bae1dSRodney W. Grimes /* 83fed06968SJulian Elischer * callout list for things to do at exit time 84fed06968SJulian Elischer */ 8593efcae8SPoul-Henning Kamp struct exitlist { 86fed06968SJulian Elischer exitlist_fn function; 87e3975643SJake Burkholder TAILQ_ENTRY(exitlist) next; 8893efcae8SPoul-Henning Kamp }; 89fed06968SJulian Elischer 90e3975643SJake Burkholder TAILQ_HEAD(exit_list_head, exitlist); 9193efcae8SPoul-Henning Kamp static struct exit_list_head exit_list = TAILQ_HEAD_INITIALIZER(exit_list); 92fed06968SJulian Elischer 93fed06968SJulian Elischer /* 94df8bae1dSRodney W. Grimes * exit -- 95df8bae1dSRodney W. Grimes * Death of process. 96df8bae1dSRodney W. Grimes */ 97fc0b1dbfSBruce Evans void 98ac2b067bSPeter Wemm sys_exit(p, uap) 99df8bae1dSRodney W. Grimes struct proc *p; 100ac2b067bSPeter Wemm struct sys_exit_args /* { 1015fdb8324SBruce Evans int rval; 1025fdb8324SBruce Evans } */ *uap; 103df8bae1dSRodney W. Grimes { 104df8bae1dSRodney W. Grimes 105df8bae1dSRodney W. Grimes exit1(p, W_EXITCODE(uap->rval, 0)); 106df8bae1dSRodney W. Grimes /* NOTREACHED */ 107df8bae1dSRodney W. Grimes } 108df8bae1dSRodney W. Grimes 109df8bae1dSRodney W. Grimes /* 110df8bae1dSRodney W. Grimes * Exit: deallocate address space and other resources, change proc state 111df8bae1dSRodney W. Grimes * to zombie, and unlink proc from allproc and parent's lists. Save exit 112df8bae1dSRodney W. Grimes * status and rusage for wait(). Check for child processes and orphan them. 113df8bae1dSRodney W. Grimes */ 114fc0b1dbfSBruce Evans void 115df8bae1dSRodney W. Grimes exit1(p, rv) 116df8bae1dSRodney W. Grimes register struct proc *p; 117df8bae1dSRodney W. Grimes int rv; 118df8bae1dSRodney W. Grimes { 119df8bae1dSRodney W. Grimes register struct proc *q, *nq; 120df8bae1dSRodney W. Grimes register struct vmspace *vm; 12193efcae8SPoul-Henning Kamp struct exitlist *ep; 122df8bae1dSRodney W. Grimes 1235f7bd355SPoul-Henning Kamp if (p->p_pid == 1) { 1245f7bd355SPoul-Henning Kamp printf("init died (signal %d, exit %d)\n", 125df8bae1dSRodney W. Grimes WTERMSIG(rv), WEXITSTATUS(rv)); 1265f7bd355SPoul-Henning Kamp panic("Going nowhere without my init!"); 1275f7bd355SPoul-Henning Kamp } 1282c1011f7SJohn Dyson 1292244ea07SJohn Dyson aio_proc_rundown(p); 1302244ea07SJohn Dyson 1312c1011f7SJohn Dyson /* are we a task leader? */ 132a914fb6bSJohn Baldwin PROC_LOCK(p); 1332c1011f7SJohn Dyson if(p == p->p_leader) { 1342c1011f7SJohn Dyson struct kill_args killArgs; 135a914fb6bSJohn Baldwin 1362c1011f7SJohn Dyson killArgs.signum = SIGKILL; 1372c1011f7SJohn Dyson q = p->p_peers; 1382c1011f7SJohn Dyson while(q) { 1392c1011f7SJohn Dyson killArgs.pid = q->p_pid; 1402c1011f7SJohn Dyson /* 1412c1011f7SJohn Dyson * The interface for kill is better 1422c1011f7SJohn Dyson * than the internal signal 1432c1011f7SJohn Dyson */ 144a914fb6bSJohn Baldwin PROC_UNLOCK(p); 145cb226aaaSPoul-Henning Kamp kill(p, &killArgs); 146a914fb6bSJohn Baldwin PROC_LOCK(p); 1472c1011f7SJohn Dyson nq = q; 1482c1011f7SJohn Dyson q = q->p_peers; 1492c1011f7SJohn Dyson } 15079fc0bf4SMike Smith while (p->p_peers) 151a914fb6bSJohn Baldwin msleep((caddr_t)p, &p->p_mtx, PWAIT, "exit1", 0); 1522c1011f7SJohn Dyson } 153a914fb6bSJohn Baldwin PROC_UNLOCK(p); 1542c1011f7SJohn Dyson 155df8bae1dSRodney W. Grimes #ifdef PGINPROF 156df8bae1dSRodney W. Grimes vmsizmon(); 157df8bae1dSRodney W. Grimes #endif 1582a024a2bSSean Eric Fagan STOPEVENT(p, S_EXIT, rv); 15989361835SSean Eric Fagan wakeup(&p->p_stype); /* Wakeup anyone in procfs' PIOCWAIT */ 1602a024a2bSSean Eric Fagan 161fed06968SJulian Elischer /* 162e9189611SPeter Wemm * Check if any loadable modules need anything done at process exit. 163fed06968SJulian Elischer * e.g. SYSV IPC stuff 164fed06968SJulian Elischer * XXX what if one of these generates an error? 165fed06968SJulian Elischer */ 16693efcae8SPoul-Henning Kamp TAILQ_FOREACH(ep, &exit_list, next) 167fed06968SJulian Elischer (*ep->function)(p); 168fed06968SJulian Elischer 169df8bae1dSRodney W. Grimes stopprofclock(p); 170a914fb6bSJohn Baldwin 171df8bae1dSRodney W. Grimes MALLOC(p->p_ru, struct rusage *, sizeof(struct rusage), 172df8bae1dSRodney W. Grimes M_ZOMBIE, M_WAITOK); 173df8bae1dSRodney W. Grimes /* 174df8bae1dSRodney W. Grimes * If parent is waiting for us to exit or exec, 175df8bae1dSRodney W. Grimes * P_PPWAIT is set; we will wakeup the parent below. 176df8bae1dSRodney W. Grimes */ 177a914fb6bSJohn Baldwin PROC_LOCK(p); 178df8bae1dSRodney W. Grimes p->p_flag &= ~(P_TRACED | P_PPWAIT); 179df8bae1dSRodney W. Grimes p->p_flag |= P_WEXIT; 1802c42a146SMarcel Moolenaar SIGEMPTYSET(p->p_siglist); 181a914fb6bSJohn Baldwin PROC_UNLOCK(p); 1824cf41af3SPoul-Henning Kamp if (timevalisset(&p->p_realtimer.it_value)) 1834f559836SJake Burkholder callout_stop(&p->p_itcallout); 184df8bae1dSRodney W. Grimes 185df8bae1dSRodney W. Grimes /* 186831d27a9SDon Lewis * Reset any sigio structures pointing to us as a result of 187831d27a9SDon Lewis * F_SETOWN with our pid. 188831d27a9SDon Lewis */ 189831d27a9SDon Lewis funsetownlst(&p->p_sigiolst); 190831d27a9SDon Lewis 191831d27a9SDon Lewis /* 192df8bae1dSRodney W. Grimes * Close open files and release open-file table. 193df8bae1dSRodney W. Grimes * This may block! 194df8bae1dSRodney W. Grimes */ 195df8bae1dSRodney W. Grimes fdfree(p); 196df8bae1dSRodney W. Grimes 197a914fb6bSJohn Baldwin /* 198a914fb6bSJohn Baldwin * Remove ourself from our leader's peer list and wake our leader. 199a914fb6bSJohn Baldwin */ 200a914fb6bSJohn Baldwin PROC_LOCK(p); 20179fc0bf4SMike Smith if(p->p_leader->p_peers) { 20279fc0bf4SMike Smith q = p->p_leader; 20379fc0bf4SMike Smith while(q->p_peers != p) 20479fc0bf4SMike Smith q = q->p_peers; 20579fc0bf4SMike Smith q->p_peers = p->p_peers; 20679fc0bf4SMike Smith wakeup((caddr_t)p->p_leader); 20779fc0bf4SMike Smith } 208a914fb6bSJohn Baldwin PROC_UNLOCK(p); 20979fc0bf4SMike Smith 21081090119SPeter Wemm /* 21181090119SPeter Wemm * XXX Shutdown SYSV semaphores 21281090119SPeter Wemm */ 213a353d785SJoerg Wunsch semexit(p); 214a353d785SJoerg Wunsch 215df8bae1dSRodney W. Grimes /* The next two chunks should probably be moved to vmspace_exit. */ 216df8bae1dSRodney W. Grimes vm = p->p_vmspace; 217df8bae1dSRodney W. Grimes /* 218df8bae1dSRodney W. Grimes * Release user portion of address space. 219df8bae1dSRodney W. Grimes * This releases references to vnodes, 220df8bae1dSRodney W. Grimes * which could cause I/O if the file has been unlinked. 221df8bae1dSRodney W. Grimes * Need to do this early enough that we can still sleep. 222df8bae1dSRodney W. Grimes * Can't free the entire vmspace as the kernel stack 223df8bae1dSRodney W. Grimes * may be mapped within that space also. 224df8bae1dSRodney W. Grimes */ 2259d3fbbb5SJohn Dyson if (vm->vm_refcnt == 1) { 226a2a1c95cSPeter Wemm if (vm->vm_shm) 227a2a1c95cSPeter Wemm shmexit(p); 228b1028ad1SLuoqi Chen pmap_remove_pages(vmspace_pmap(vm), VM_MIN_ADDRESS, 2299d3fbbb5SJohn Dyson VM_MAXUSER_ADDRESS); 23067bf6868SJohn Dyson (void) vm_map_remove(&vm->vm_map, VM_MIN_ADDRESS, 23167bf6868SJohn Dyson VM_MAXUSER_ADDRESS); 2329d3fbbb5SJohn Dyson } 233df8bae1dSRodney W. Grimes 234a914fb6bSJohn Baldwin PROC_LOCK(p); 235df8bae1dSRodney W. Grimes if (SESS_LEADER(p)) { 236df8bae1dSRodney W. Grimes register struct session *sp = p->p_session; 237df8bae1dSRodney W. Grimes 238a914fb6bSJohn Baldwin PROC_UNLOCK(p); 239df8bae1dSRodney W. Grimes if (sp->s_ttyvp) { 240df8bae1dSRodney W. Grimes /* 241df8bae1dSRodney W. Grimes * Controlling process. 242df8bae1dSRodney W. Grimes * Signal foreground pgrp, 243df8bae1dSRodney W. Grimes * drain controlling terminal 244df8bae1dSRodney W. Grimes * and revoke access to controlling terminal. 245df8bae1dSRodney W. Grimes */ 246dd45d8adSJulian Elischer if (sp->s_ttyp && (sp->s_ttyp->t_session == sp)) { 247df8bae1dSRodney W. Grimes if (sp->s_ttyp->t_pgrp) 248df8bae1dSRodney W. Grimes pgsignal(sp->s_ttyp->t_pgrp, SIGHUP, 1); 249df8bae1dSRodney W. Grimes (void) ttywait(sp->s_ttyp); 250df8bae1dSRodney W. Grimes /* 251df8bae1dSRodney W. Grimes * The tty could have been revoked 252df8bae1dSRodney W. Grimes * if we blocked. 253df8bae1dSRodney W. Grimes */ 254df8bae1dSRodney W. Grimes if (sp->s_ttyvp) 255996c772fSJohn Dyson VOP_REVOKE(sp->s_ttyvp, REVOKEALL); 256df8bae1dSRodney W. Grimes } 257df8bae1dSRodney W. Grimes if (sp->s_ttyvp) 258df8bae1dSRodney W. Grimes vrele(sp->s_ttyvp); 259df8bae1dSRodney W. Grimes sp->s_ttyvp = NULL; 260df8bae1dSRodney W. Grimes /* 261df8bae1dSRodney W. Grimes * s_ttyp is not zero'd; we use this to indicate 262df8bae1dSRodney W. Grimes * that the session once had a controlling terminal. 263df8bae1dSRodney W. Grimes * (for logging and informational purposes) 264df8bae1dSRodney W. Grimes */ 265df8bae1dSRodney W. Grimes } 266df8bae1dSRodney W. Grimes sp->s_leader = NULL; 267a914fb6bSJohn Baldwin } else 268a914fb6bSJohn Baldwin PROC_UNLOCK(p); 269df8bae1dSRodney W. Grimes fixjobc(p, p->p_pgrp, 0); 270df8bae1dSRodney W. Grimes (void)acct_process(p); 271df8bae1dSRodney W. Grimes #ifdef KTRACE 272df8bae1dSRodney W. Grimes /* 273df8bae1dSRodney W. Grimes * release trace file 274df8bae1dSRodney W. Grimes */ 275df8bae1dSRodney W. Grimes p->p_traceflag = 0; /* don't trace the vrele() */ 276df8bae1dSRodney W. Grimes if (p->p_tracep) 277df8bae1dSRodney W. Grimes vrele(p->p_tracep); 278df8bae1dSRodney W. Grimes #endif 279df8bae1dSRodney W. Grimes /* 280df8bae1dSRodney W. Grimes * Remove proc from allproc queue and pidhash chain. 281df8bae1dSRodney W. Grimes * Place onto zombproc. Unlink from parent's child list. 282df8bae1dSRodney W. Grimes */ 2831005a129SJohn Baldwin sx_xlock(&allproc_lock); 284b75356e1SJeffrey Hsu LIST_REMOVE(p, p_list); 285b75356e1SJeffrey Hsu LIST_INSERT_HEAD(&zombproc, p, p_list); 286b75356e1SJeffrey Hsu LIST_REMOVE(p, p_hash); 2871005a129SJohn Baldwin sx_xunlock(&allproc_lock); 288df8bae1dSRodney W. Grimes 2891005a129SJohn Baldwin sx_xlock(&proctree_lock); 2902e3c8fcbSPoul-Henning Kamp q = LIST_FIRST(&p->p_children); 291a914fb6bSJohn Baldwin if (q != NULL) /* only need this if any child is S_ZOMB */ 292df8bae1dSRodney W. Grimes wakeup((caddr_t) initproc); 293a914fb6bSJohn Baldwin for (; q != NULL; q = nq) { 2942e3c8fcbSPoul-Henning Kamp nq = LIST_NEXT(q, p_sibling); 295a914fb6bSJohn Baldwin PROC_LOCK(q); 296c65437a3SJohn Baldwin proc_reparent(q, initproc); 2974ac9ae70SJulian Elischer q->p_sigparent = SIGCHLD; 298df8bae1dSRodney W. Grimes /* 299df8bae1dSRodney W. Grimes * Traced processes are killed 300df8bae1dSRodney W. Grimes * since their existence means someone is screwing up. 301df8bae1dSRodney W. Grimes */ 302df8bae1dSRodney W. Grimes if (q->p_flag & P_TRACED) { 303df8bae1dSRodney W. Grimes q->p_flag &= ~P_TRACED; 304df8bae1dSRodney W. Grimes psignal(q, SIGKILL); 305c65437a3SJohn Baldwin } 306a914fb6bSJohn Baldwin PROC_UNLOCK(q); 307df8bae1dSRodney W. Grimes } 308df8bae1dSRodney W. Grimes 309df8bae1dSRodney W. Grimes /* 310df8bae1dSRodney W. Grimes * Save exit status and final rusage info, adding in child rusage 311df8bae1dSRodney W. Grimes * info and self times. 312df8bae1dSRodney W. Grimes */ 313df8bae1dSRodney W. Grimes p->p_xstat = rv; 314df8bae1dSRodney W. Grimes *p->p_ru = p->p_stats->p_ru; 3159ed346baSBosko Milekic mtx_lock_spin(&sched_lock); 316df8bae1dSRodney W. Grimes calcru(p, &p->p_ru->ru_utime, &p->p_ru->ru_stime, NULL); 3179ed346baSBosko Milekic mtx_unlock_spin(&sched_lock); 318df8bae1dSRodney W. Grimes ruadd(p->p_ru, &p->p_stats->p_cru); 319df8bae1dSRodney W. Grimes 320df8bae1dSRodney W. Grimes /* 32156ce1a8dSBruce Evans * Pretend that an mi_switch() to the next process occurs now. We 32256ce1a8dSBruce Evans * must set `switchtime' directly since we will call cpu_switch() 32356ce1a8dSBruce Evans * directly. Set it now so that the rest of the exit time gets 32456ce1a8dSBruce Evans * counted somewhere if possible. 32556ce1a8dSBruce Evans */ 3260d139b37STor Egge mtx_lock_spin(&sched_lock); 3279d0ddf18STor Egge microuptime(PCPU_PTR(switchtime)); 328ef73ae4bSJake Burkholder PCPU_SET(switchticks, ticks); 3299d0ddf18STor Egge mtx_unlock_spin(&sched_lock); 33056ce1a8dSBruce Evans 33156ce1a8dSBruce Evans /* 332a274d19bSBrian Feldman * notify interested parties of our demise. 333cb679c38SJonathan Lemon */ 334a914fb6bSJohn Baldwin PROC_LOCK(p); 335a274d19bSBrian Feldman KNOTE(&p->p_klist, NOTE_EXIT); 336cb679c38SJonathan Lemon 337cb679c38SJonathan Lemon /* 338645682fdSLuoqi Chen * Notify parent that we're gone. If parent has the PS_NOCLDWAIT 339245f17d4SJoerg Wunsch * flag set, notify process 1 instead (and hope it will handle 340245f17d4SJoerg Wunsch * this situation). 341df8bae1dSRodney W. Grimes */ 342645682fdSLuoqi Chen if (p->p_pptr->p_procsig->ps_flag & PS_NOCLDWAIT) { 343245f17d4SJoerg Wunsch struct proc *pp = p->p_pptr; 344245f17d4SJoerg Wunsch proc_reparent(p, initproc); 345245f17d4SJoerg Wunsch /* 346245f17d4SJoerg Wunsch * If this was the last child of our parent, notify 347245f17d4SJoerg Wunsch * parent, so in case he was wait(2)ing, he will 348245f17d4SJoerg Wunsch * continue. 349245f17d4SJoerg Wunsch */ 350245f17d4SJoerg Wunsch if (LIST_EMPTY(&pp->p_children)) 351245f17d4SJoerg Wunsch wakeup((caddr_t)pp); 352245f17d4SJoerg Wunsch } 353245f17d4SJoerg Wunsch 354c65437a3SJohn Baldwin PROC_LOCK(p->p_pptr); 355c65437a3SJohn Baldwin if (p->p_sigparent && p->p_pptr != initproc) 3566626c604SJulian Elischer psignal(p->p_pptr, p->p_sigparent); 357c65437a3SJohn Baldwin else 3586626c604SJulian Elischer psignal(p->p_pptr, SIGCHLD); 359c65437a3SJohn Baldwin PROC_UNLOCK(p->p_pptr); 360c65437a3SJohn Baldwin PROC_UNLOCK(p); 3611005a129SJohn Baldwin sx_xunlock(&proctree_lock); 362c65437a3SJohn Baldwin 363df8bae1dSRodney W. Grimes /* 364df8bae1dSRodney W. Grimes * Clear curproc after we've done all operations 365df8bae1dSRodney W. Grimes * that could block, and before tearing down the rest 366df8bae1dSRodney W. Grimes * of the process state that might be used from clock, etc. 367df8bae1dSRodney W. Grimes * Also, can't clear curproc while we're still runnable, 368df8bae1dSRodney W. Grimes * as we're not on a run queue (we are current, just not 369df8bae1dSRodney W. Grimes * a proper proc any longer!). 370df8bae1dSRodney W. Grimes * 371df8bae1dSRodney W. Grimes * Other substructures are freed from wait(). 372df8bae1dSRodney W. Grimes */ 373a914fb6bSJohn Baldwin mtx_assert(&Giant, MA_OWNED); 374be6a1d14SDavid Greenman if (--p->p_limit->p_refcnt == 0) { 375df8bae1dSRodney W. Grimes FREE(p->p_limit, M_SUBPROC); 376be6a1d14SDavid Greenman p->p_limit = NULL; 377be6a1d14SDavid Greenman } 378df8bae1dSRodney W. Grimes 379df8bae1dSRodney W. Grimes /* 380df8bae1dSRodney W. Grimes * Finally, call machine-dependent code to release the remaining 381df8bae1dSRodney W. Grimes * resources including address space, the kernel stack and pcb. 382df8bae1dSRodney W. Grimes * The address space is released by "vmspace_free(p->p_vmspace)"; 383df8bae1dSRodney W. Grimes * This is machine-dependent, as we may have to change stacks 384df8bae1dSRodney W. Grimes * or ensure that the current one isn't reallocated before we 38578d7e629SBruce Evans * finish. cpu_exit will end with a call to cpu_switch(), finishing 386df8bae1dSRodney W. Grimes * our execution (pun intended). 387df8bae1dSRodney W. Grimes */ 388df8bae1dSRodney W. Grimes cpu_exit(p); 389df8bae1dSRodney W. Grimes } 390df8bae1dSRodney W. Grimes 391b2f9e8b1SBruce Evans #ifdef COMPAT_43 39226f9a767SRodney W. Grimes int 393cb226aaaSPoul-Henning Kamp owait(p, uap) 394df8bae1dSRodney W. Grimes struct proc *p; 3955fdb8324SBruce Evans register struct owait_args /* { 3965fdb8324SBruce Evans int dummy; 3975fdb8324SBruce Evans } */ *uap; 398df8bae1dSRodney W. Grimes { 39993c9414eSSteven Wallace struct wait_args w; 400df8bae1dSRodney W. Grimes 40193c9414eSSteven Wallace w.options = 0; 40293c9414eSSteven Wallace w.rusage = NULL; 40393c9414eSSteven Wallace w.pid = WAIT_ANY; 40493c9414eSSteven Wallace w.status = NULL; 40501166e92SBruce Evans return (wait1(p, &w, 1)); 406df8bae1dSRodney W. Grimes } 407b2f9e8b1SBruce Evans #endif /* COMPAT_43 */ 408df8bae1dSRodney W. Grimes 40926f9a767SRodney W. Grimes int 410cb226aaaSPoul-Henning Kamp wait4(p, uap) 411df8bae1dSRodney W. Grimes struct proc *p; 412df8bae1dSRodney W. Grimes struct wait_args *uap; 413df8bae1dSRodney W. Grimes { 4145fdb8324SBruce Evans 41501166e92SBruce Evans return (wait1(p, uap, 0)); 416df8bae1dSRodney W. Grimes } 417df8bae1dSRodney W. Grimes 41893c9414eSSteven Wallace static int 41901166e92SBruce Evans wait1(q, uap, compat) 420df8bae1dSRodney W. Grimes register struct proc *q; 4215fdb8324SBruce Evans register struct wait_args /* { 4225fdb8324SBruce Evans int pid; 4235fdb8324SBruce Evans int *status; 4245fdb8324SBruce Evans int options; 4255fdb8324SBruce Evans struct rusage *rusage; 4265fdb8324SBruce Evans } */ *uap; 42793c9414eSSteven Wallace int compat; 428df8bae1dSRodney W. Grimes { 429df8bae1dSRodney W. Grimes register int nfound; 430df8bae1dSRodney W. Grimes register struct proc *p, *t; 431f23c6d68SSteven Wallace int status, error; 432df8bae1dSRodney W. Grimes 433df8bae1dSRodney W. Grimes if (uap->pid == 0) 434df8bae1dSRodney W. Grimes uap->pid = -q->p_pgid; 4354ac9ae70SJulian Elischer if (uap->options &~ (WUNTRACED|WNOHANG|WLINUXCLONE)) 436df8bae1dSRodney W. Grimes return (EINVAL); 437df8bae1dSRodney W. Grimes loop: 438df8bae1dSRodney W. Grimes nfound = 0; 4391005a129SJohn Baldwin sx_slock(&proctree_lock); 4402e3c8fcbSPoul-Henning Kamp LIST_FOREACH(p, &q->p_children, p_sibling) { 441df8bae1dSRodney W. Grimes if (uap->pid != WAIT_ANY && 442df8bae1dSRodney W. Grimes p->p_pid != uap->pid && p->p_pgid != -uap->pid) 443df8bae1dSRodney W. Grimes continue; 4444ac9ae70SJulian Elischer 4451156bc4dSJake Burkholder /* 4461156bc4dSJake Burkholder * This special case handles a kthread spawned by linux_clone 4471156bc4dSJake Burkholder * (see linux_misc.c). The linux_wait4 and linux_waitpid 4481156bc4dSJake Burkholder * functions need to be able to distinguish between waiting 4491156bc4dSJake Burkholder * on a process and waiting on a thread. It is a thread if 4501156bc4dSJake Burkholder * p_sigparent is not SIGCHLD, and the WLINUXCLONE option 4511156bc4dSJake Burkholder * signifies we want to wait for threads and not processes. 4524ac9ae70SJulian Elischer */ 453a914fb6bSJohn Baldwin PROC_LOCK(p); 4541156bc4dSJake Burkholder if ((p->p_sigparent != SIGCHLD) ^ 455a914fb6bSJohn Baldwin ((uap->options & WLINUXCLONE) != 0)) { 456a914fb6bSJohn Baldwin PROC_UNLOCK(p); 4574ac9ae70SJulian Elischer continue; 458a914fb6bSJohn Baldwin } 4594ac9ae70SJulian Elischer 460df8bae1dSRodney W. Grimes nfound++; 4619ed346baSBosko Milekic mtx_lock_spin(&sched_lock); 462df8bae1dSRodney W. Grimes if (p->p_stat == SZOMB) { 4630d2afceeSDavid Greenman /* charge childs scheduling cpu usage to parent */ 464d5c4431eSDavid Greenman if (curproc->p_pid != 1) { 465bdf42357SBruce Evans curproc->p_estcpu = 466bdf42357SBruce Evans ESTCPULIM(curproc->p_estcpu + p->p_estcpu); 467d5c4431eSDavid Greenman } 4680d2afceeSDavid Greenman 469c65437a3SJohn Baldwin mtx_unlock_spin(&sched_lock); 470c65437a3SJohn Baldwin PROC_UNLOCK(p); 4711005a129SJohn Baldwin sx_sunlock(&proctree_lock); 472c65437a3SJohn Baldwin 47301166e92SBruce Evans q->p_retval[0] = p->p_pid; 474b2f9e8b1SBruce Evans #ifdef COMPAT_43 47593c9414eSSteven Wallace if (compat) 47601166e92SBruce Evans q->p_retval[1] = p->p_xstat; 477df8bae1dSRodney W. Grimes else 478df8bae1dSRodney W. Grimes #endif 479df8bae1dSRodney W. Grimes if (uap->status) { 480df8bae1dSRodney W. Grimes status = p->p_xstat; /* convert to int */ 481bb56ec4aSPoul-Henning Kamp if ((error = copyout((caddr_t)&status, 482bb56ec4aSPoul-Henning Kamp (caddr_t)uap->status, sizeof(status)))) 483df8bae1dSRodney W. Grimes return (error); 484df8bae1dSRodney W. Grimes } 485df8bae1dSRodney W. Grimes if (uap->rusage && (error = copyout((caddr_t)p->p_ru, 486df8bae1dSRodney W. Grimes (caddr_t)uap->rusage, sizeof (struct rusage)))) 487df8bae1dSRodney W. Grimes return (error); 488df8bae1dSRodney W. Grimes /* 489df8bae1dSRodney W. Grimes * If we got the child via a ptrace 'attach', 490df8bae1dSRodney W. Grimes * we need to give it back to the old parent. 491df8bae1dSRodney W. Grimes */ 4921005a129SJohn Baldwin sx_xlock(&proctree_lock); 493c65437a3SJohn Baldwin if (p->p_oppid) { 49498f03f90SJake Burkholder if ((t = pfind(p->p_oppid)) != NULL) { 495c65437a3SJohn Baldwin PROC_LOCK(p); 496df8bae1dSRodney W. Grimes p->p_oppid = 0; 497df8bae1dSRodney W. Grimes proc_reparent(p, t); 498c65437a3SJohn Baldwin PROC_UNLOCK(p); 499df8bae1dSRodney W. Grimes psignal(t, SIGCHLD); 50033a9ed9dSJohn Baldwin wakeup((caddr_t)t); 501c65437a3SJohn Baldwin PROC_UNLOCK(t); 5021005a129SJohn Baldwin sx_xunlock(&proctree_lock); 503df8bae1dSRodney W. Grimes return (0); 504df8bae1dSRodney W. Grimes } 50598f03f90SJake Burkholder } 5061005a129SJohn Baldwin sx_xunlock(&proctree_lock); 507c65437a3SJohn Baldwin PROC_LOCK(p); 508df8bae1dSRodney W. Grimes p->p_xstat = 0; 509c65437a3SJohn Baldwin PROC_UNLOCK(p); 510df8bae1dSRodney W. Grimes ruadd(&q->p_stats->p_cru, p->p_ru); 511df8bae1dSRodney W. Grimes FREE(p->p_ru, M_ZOMBIE); 512be6a1d14SDavid Greenman p->p_ru = NULL; 513df8bae1dSRodney W. Grimes 514df8bae1dSRodney W. Grimes /* 515df8bae1dSRodney W. Grimes * Decrement the count of procs running with this uid. 516df8bae1dSRodney W. Grimes */ 517f535380cSDon Lewis (void)chgproccnt(p->p_cred->p_uidinfo, -1, 0); 518df8bae1dSRodney W. Grimes 519df8bae1dSRodney W. Grimes /* 520bd7e5f99SJohn Dyson * Release reference to text vnode 521bd7e5f99SJohn Dyson */ 522bd7e5f99SJohn Dyson if (p->p_textvp) 523bd7e5f99SJohn Dyson vrele(p->p_textvp); 524bd7e5f99SJohn Dyson 525bd7e5f99SJohn Dyson /* 526df8bae1dSRodney W. Grimes * Free up credentials. 527df8bae1dSRodney W. Grimes */ 528a914fb6bSJohn Baldwin PROC_LOCK(p); 529df8bae1dSRodney W. Grimes if (--p->p_cred->p_refcnt == 0) { 530da654d90SPoul-Henning Kamp crfree(p->p_ucred); 531f535380cSDon Lewis uifree(p->p_cred->p_uidinfo); 532df8bae1dSRodney W. Grimes FREE(p->p_cred, M_SUBPROC); 533be6a1d14SDavid Greenman p->p_cred = NULL; 534df8bae1dSRodney W. Grimes } 535df8bae1dSRodney W. Grimes 536df8bae1dSRodney W. Grimes /* 537b9df5231SPoul-Henning Kamp * Remove unused arguments 538b9df5231SPoul-Henning Kamp */ 539b9df5231SPoul-Henning Kamp if (p->p_args && --p->p_args->ar_ref == 0) 540b9df5231SPoul-Henning Kamp FREE(p->p_args, M_PARGS); 541a914fb6bSJohn Baldwin PROC_UNLOCK(p); 542b9df5231SPoul-Henning Kamp 543b9df5231SPoul-Henning Kamp /* 544df8bae1dSRodney W. Grimes * Finally finished with old proc entry. 545df8bae1dSRodney W. Grimes * Unlink it from its process group and free it. 546df8bae1dSRodney W. Grimes */ 547df8bae1dSRodney W. Grimes leavepgrp(p); 54898f03f90SJake Burkholder 5491005a129SJohn Baldwin sx_xlock(&allproc_lock); 550b75356e1SJeffrey Hsu LIST_REMOVE(p, p_list); /* off zombproc */ 5511005a129SJohn Baldwin sx_xunlock(&allproc_lock); 55298f03f90SJake Burkholder 5531005a129SJohn Baldwin sx_xlock(&proctree_lock); 554b75356e1SJeffrey Hsu LIST_REMOVE(p, p_sibling); 5551005a129SJohn Baldwin sx_xunlock(&proctree_lock); 556df8bae1dSRodney W. Grimes 557a914fb6bSJohn Baldwin PROC_LOCK(p); 5586626c604SJulian Elischer if (--p->p_procsig->ps_refcnt == 0) { 559dc9c271aSJulian Elischer if (p->p_sigacts != &p->p_addr->u_sigacts) 560dc9c271aSJulian Elischer FREE(p->p_sigacts, M_SUBPROC); 561dc9c271aSJulian Elischer FREE(p->p_procsig, M_SUBPROC); 5626626c604SJulian Elischer p->p_procsig = NULL; 5636626c604SJulian Elischer } 564a914fb6bSJohn Baldwin PROC_UNLOCK(p); 56588c5ea45SJulian Elischer 566df8bae1dSRodney W. Grimes /* 567df8bae1dSRodney W. Grimes * Give machine-dependent layer a chance 568df8bae1dSRodney W. Grimes * to free anything that cpu_exit couldn't 569df8bae1dSRodney W. Grimes * release while still running in process context. 570df8bae1dSRodney W. Grimes */ 571df8bae1dSRodney W. Grimes cpu_wait(p); 5724971f62aSJohn Baldwin mtx_destroy(&p->p_mtx); 5732d8acc0fSJohn Dyson zfree(proc_zone, p); 574df8bae1dSRodney W. Grimes nprocs--; 575df8bae1dSRodney W. Grimes return (0); 576df8bae1dSRodney W. Grimes } 577df8bae1dSRodney W. Grimes if (p->p_stat == SSTOP && (p->p_flag & P_WAITED) == 0 && 578df8bae1dSRodney W. Grimes (p->p_flag & P_TRACED || uap->options & WUNTRACED)) { 5799ed346baSBosko Milekic mtx_unlock_spin(&sched_lock); 580df8bae1dSRodney W. Grimes p->p_flag |= P_WAITED; 581a914fb6bSJohn Baldwin PROC_UNLOCK(p); 5821005a129SJohn Baldwin sx_sunlock(&proctree_lock); 58301166e92SBruce Evans q->p_retval[0] = p->p_pid; 584b2f9e8b1SBruce Evans #ifdef COMPAT_43 58593c9414eSSteven Wallace if (compat) { 58601166e92SBruce Evans q->p_retval[1] = W_STOPCODE(p->p_xstat); 587df8bae1dSRodney W. Grimes error = 0; 588df8bae1dSRodney W. Grimes } else 589df8bae1dSRodney W. Grimes #endif 590df8bae1dSRodney W. Grimes if (uap->status) { 591df8bae1dSRodney W. Grimes status = W_STOPCODE(p->p_xstat); 592df8bae1dSRodney W. Grimes error = copyout((caddr_t)&status, 593df8bae1dSRodney W. Grimes (caddr_t)uap->status, sizeof(status)); 594df8bae1dSRodney W. Grimes } else 595df8bae1dSRodney W. Grimes error = 0; 596df8bae1dSRodney W. Grimes return (error); 597df8bae1dSRodney W. Grimes } 5989ed346baSBosko Milekic mtx_unlock_spin(&sched_lock); 599a914fb6bSJohn Baldwin PROC_UNLOCK(p); 600df8bae1dSRodney W. Grimes } 6011005a129SJohn Baldwin sx_sunlock(&proctree_lock); 602df8bae1dSRodney W. Grimes if (nfound == 0) 603df8bae1dSRodney W. Grimes return (ECHILD); 604df8bae1dSRodney W. Grimes if (uap->options & WNOHANG) { 60501166e92SBruce Evans q->p_retval[0] = 0; 606df8bae1dSRodney W. Grimes return (0); 607df8bae1dSRodney W. Grimes } 608bb56ec4aSPoul-Henning Kamp if ((error = tsleep((caddr_t)q, PWAIT | PCATCH, "wait", 0))) 609df8bae1dSRodney W. Grimes return (error); 610df8bae1dSRodney W. Grimes goto loop; 611df8bae1dSRodney W. Grimes } 612df8bae1dSRodney W. Grimes 613df8bae1dSRodney W. Grimes /* 61498f03f90SJake Burkholder * Make process 'parent' the new parent of process 'child'. 61598f03f90SJake Burkholder * Must be called with an exclusive hold of proctree lock. 616df8bae1dSRodney W. Grimes */ 617df8bae1dSRodney W. Grimes void 618df8bae1dSRodney W. Grimes proc_reparent(child, parent) 619df8bae1dSRodney W. Grimes register struct proc *child; 620df8bae1dSRodney W. Grimes register struct proc *parent; 621df8bae1dSRodney W. Grimes { 622df8bae1dSRodney W. Grimes 6231005a129SJohn Baldwin SX_ASSERT_XLOCKED(&proctree_lock); 624c65437a3SJohn Baldwin PROC_LOCK_ASSERT(child, MA_OWNED); 625df8bae1dSRodney W. Grimes if (child->p_pptr == parent) 626df8bae1dSRodney W. Grimes return; 627df8bae1dSRodney W. Grimes 628b75356e1SJeffrey Hsu LIST_REMOVE(child, p_sibling); 629b75356e1SJeffrey Hsu LIST_INSERT_HEAD(&parent->p_children, child, p_sibling); 630df8bae1dSRodney W. Grimes child->p_pptr = parent; 631df8bae1dSRodney W. Grimes } 632fed06968SJulian Elischer 633e0d898b4SJulian Elischer /* 634e0d898b4SJulian Elischer * The next two functions are to handle adding/deleting items on the 635fed06968SJulian Elischer * exit callout list 636e0d898b4SJulian Elischer * 637e0d898b4SJulian Elischer * at_exit(): 638e0d898b4SJulian Elischer * Take the arguments given and put them onto the exit callout list, 639fed06968SJulian Elischer * However first make sure that it's not already there. 640fed06968SJulian Elischer * returns 0 on success. 641fed06968SJulian Elischer */ 64293efcae8SPoul-Henning Kamp 643fed06968SJulian Elischer int 644eb776aeaSBruce Evans at_exit(function) 645eb776aeaSBruce Evans exitlist_fn function; 646fed06968SJulian Elischer { 64793efcae8SPoul-Henning Kamp struct exitlist *ep; 648e0d898b4SJulian Elischer 64993efcae8SPoul-Henning Kamp #ifdef INVARIANTS 650e0d898b4SJulian Elischer /* Be noisy if the programmer has lost track of things */ 651e0d898b4SJulian Elischer if (rm_at_exit(function)) 65293efcae8SPoul-Henning Kamp printf("WARNING: exit callout entry (%p) already present\n", 65393efcae8SPoul-Henning Kamp function); 65493efcae8SPoul-Henning Kamp #endif 65593efcae8SPoul-Henning Kamp ep = malloc(sizeof(*ep), M_ATEXIT, M_NOWAIT); 656e0d898b4SJulian Elischer if (ep == NULL) 657e0d898b4SJulian Elischer return (ENOMEM); 658fed06968SJulian Elischer ep->function = function; 65993efcae8SPoul-Henning Kamp TAILQ_INSERT_TAIL(&exit_list, ep, next); 660e0d898b4SJulian Elischer return (0); 661fed06968SJulian Elischer } 66293efcae8SPoul-Henning Kamp 663fed06968SJulian Elischer /* 66493efcae8SPoul-Henning Kamp * Scan the exit callout list for the given item and remove it. 66593efcae8SPoul-Henning Kamp * Returns the number of items removed (0 or 1) 666fed06968SJulian Elischer */ 667fed06968SJulian Elischer int 668eb776aeaSBruce Evans rm_at_exit(function) 669eb776aeaSBruce Evans exitlist_fn function; 670fed06968SJulian Elischer { 67193efcae8SPoul-Henning Kamp struct exitlist *ep; 672fed06968SJulian Elischer 67393efcae8SPoul-Henning Kamp TAILQ_FOREACH(ep, &exit_list, next) { 674fed06968SJulian Elischer if (ep->function == function) { 67593efcae8SPoul-Henning Kamp TAILQ_REMOVE(&exit_list, ep, next); 67693efcae8SPoul-Henning Kamp free(ep, M_ATEXIT); 67793efcae8SPoul-Henning Kamp return(1); 678fed06968SJulian Elischer } 679fed06968SJulian Elischer } 68093efcae8SPoul-Henning Kamp return (0); 681fed06968SJulian Elischer } 682dc9c271aSJulian Elischer 683dc9c271aSJulian Elischer void check_sigacts (void) 684dc9c271aSJulian Elischer { 685dc9c271aSJulian Elischer struct proc *p = curproc; 686dc9c271aSJulian Elischer struct sigacts *pss; 687dc9c271aSJulian Elischer int s; 688dc9c271aSJulian Elischer 689a914fb6bSJohn Baldwin PROC_LOCK(p); 690dc9c271aSJulian Elischer if (p->p_procsig->ps_refcnt == 1 && 691dc9c271aSJulian Elischer p->p_sigacts != &p->p_addr->u_sigacts) { 692dc9c271aSJulian Elischer pss = p->p_sigacts; 693dc9c271aSJulian Elischer s = splhigh(); 694dc9c271aSJulian Elischer p->p_addr->u_sigacts = *pss; 695dc9c271aSJulian Elischer p->p_sigacts = &p->p_addr->u_sigacts; 696dc9c271aSJulian Elischer splx(s); 697dc9c271aSJulian Elischer FREE(pss, M_SUBPROC); 698dc9c271aSJulian Elischer } 699a914fb6bSJohn Baldwin PROC_UNLOCK(p); 700dc9c271aSJulian Elischer } 70188c5ea45SJulian Elischer 702