kern_exit.c revision 3451
1234285Sdim/*- 2234285Sdim * Copyright (c) 1982, 1986, 1989, 1991, 1993 3234285Sdim * The Regents of the University of California. All rights reserved. 4234285Sdim * (c) UNIX System Laboratories, Inc. 5234285Sdim * All or some portions of this file are derived from material licensed 6234285Sdim * to the University of California by American Telephone and Telegraph 7234285Sdim * Co. or Unix System Laboratories, Inc. and are reproduced herein with 8234285Sdim * the permission of UNIX System Laboratories, Inc. 9234285Sdim * 10234285Sdim * Redistribution and use in source and binary forms, with or without 11234285Sdim * modification, are permitted provided that the following conditions 12234285Sdim * are met: 13234285Sdim * 1. Redistributions of source code must retain the above copyright 14234285Sdim * notice, this list of conditions and the following disclaimer. 15234285Sdim * 2. Redistributions in binary form must reproduce the above copyright 16234285Sdim * notice, this list of conditions and the following disclaimer in the 17234285Sdim * documentation and/or other materials provided with the distribution. 18234285Sdim * 3. All advertising materials mentioning features or use of this software 19251662Sdim * must display the following acknowledgement: 20249423Sdim * This product includes software developed by the University of 21251662Sdim * California, Berkeley and its contributors. 22234285Sdim * 4. Neither the name of the University nor the names of its contributors 23234285Sdim * may be used to endorse or promote products derived from this software 24234285Sdim * without specific prior written permission. 25234285Sdim * 26234285Sdim * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27234285Sdim * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28234285Sdim * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29263508Sdim * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30234285Sdim * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31263508Sdim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32251662Sdim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33251662Sdim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34234285Sdim * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35234285Sdim * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36234285Sdim * SUCH DAMAGE. 37234285Sdim * 38234285Sdim * @(#)kern_exit.c 8.7 (Berkeley) 2/12/94 39234285Sdim * $Id: kern_exit.c,v 1.8 1994/10/02 17:35:14 phk Exp $ 40234285Sdim */ 41234285Sdim 42234285Sdim#include <sys/param.h> 43234285Sdim#include <sys/systm.h> 44234285Sdim#include <sys/sysent.h> 45234285Sdim#include <sys/ioctl.h> 46234285Sdim#include <sys/proc.h> 47234285Sdim#include <sys/tty.h> 48234285Sdim#include <sys/time.h> 49234285Sdim#include <sys/resource.h> 50234285Sdim#include <sys/kernel.h> 51234285Sdim#include <sys/buf.h> 52234285Sdim#include <sys/wait.h> 53234285Sdim#include <sys/file.h> 54234285Sdim#include <sys/vnode.h> 55234285Sdim#include <sys/syslog.h> 56234285Sdim#include <sys/malloc.h> 57234285Sdim#include <sys/resourcevar.h> 58234285Sdim#include <sys/signalvar.h> 59234285Sdim#include <sys/ptrace.h> 60234285Sdim#include <sys/shm.h> 61234285Sdim#include <sys/filedesc.h> 62234285Sdim 63234285Sdim#include <machine/cpu.h> 64234285Sdim#ifdef COMPAT_43 65234285Sdim#include <machine/reg.h> 66234285Sdim#include <machine/psl.h> 67234285Sdim#endif 68234285Sdim 69234285Sdim#include <vm/vm.h> 70234285Sdim#include <vm/vm_kern.h> 71234285Sdim 72249423Sdim/* 73249423Sdim * exit -- 74249423Sdim * Death of process. 75249423Sdim */ 76234285Sdimstruct rexit_args { 77234285Sdim int rval; 78234285Sdim}; 79234285Sdim__dead void 80234285Sdimexit(p, uap, retval) 81234285Sdim struct proc *p; 82234285Sdim struct rexit_args *uap; 83234285Sdim int *retval; 84234285Sdim{ 85234285Sdim 86234285Sdim exit1(p, W_EXITCODE(uap->rval, 0)); 87234285Sdim /* NOTREACHED */ 88234285Sdim while (1); 89234285Sdim} 90234285Sdim 91234285Sdim/* 92234285Sdim * Exit: deallocate address space and other resources, change proc state 93234285Sdim * to zombie, and unlink proc from allproc and parent's lists. Save exit 94234285Sdim * status and rusage for wait(). Check for child processes and orphan them. 95234285Sdim */ 96234285Sdim__dead void 97234285Sdimexit1(p, rv) 98234285Sdim register struct proc *p; 99234285Sdim int rv; 100234285Sdim{ 101234285Sdim register struct proc *q, *nq; 102234285Sdim register struct proc **pp; 103234285Sdim register struct vmspace *vm; 104234285Sdim 105234285Sdim if (p->p_pid == 1) 106234285Sdim panic("init died (signal %d, exit %d)", 107234285Sdim WTERMSIG(rv), WEXITSTATUS(rv)); 108234285Sdim#ifdef PGINPROF 109234285Sdim vmsizmon(); 110234285Sdim#endif 111234285Sdim if (p->p_flag & P_PROFIL) 112234285Sdim stopprofclock(p); 113234285Sdim MALLOC(p->p_ru, struct rusage *, sizeof(struct rusage), 114234285Sdim M_ZOMBIE, M_WAITOK); 115234285Sdim /* 116234285Sdim * If parent is waiting for us to exit or exec, 117251662Sdim * P_PPWAIT is set; we will wakeup the parent below. 118234285Sdim */ 119234285Sdim p->p_flag &= ~(P_TRACED | P_PPWAIT); 120234285Sdim p->p_flag |= P_WEXIT; 121234285Sdim p->p_sigignore = ~0; 122234285Sdim p->p_siglist = 0; 123239462Sdim untimeout(realitexpire, (caddr_t)p); 124234285Sdim 125234285Sdim /* 126234285Sdim * Close open files and release open-file table. 127234285Sdim * This may block! 128234285Sdim */ 129234285Sdim fdfree(p); 130234285Sdim 131234285Sdim /* The next two chunks should probably be moved to vmspace_exit. */ 132234285Sdim vm = p->p_vmspace; 133234285Sdim#ifdef SYSVSHM 134251662Sdim if (vm->vm_shm) 135251662Sdim shmexit(p); 136251662Sdim#endif 137249423Sdim /* 138251662Sdim * Release user portion of address space. 139234285Sdim * This releases references to vnodes, 140234285Sdim * which could cause I/O if the file has been unlinked. 141234285Sdim * Need to do this early enough that we can still sleep. 142234285Sdim * Can't free the entire vmspace as the kernel stack 143234285Sdim * may be mapped within that space also. 144234285Sdim */ 145234285Sdim if (vm->vm_refcnt == 1) 146234285Sdim (void) vm_map_remove(&vm->vm_map, VM_MIN_ADDRESS, 147234285Sdim VM_MAXUSER_ADDRESS); 148234285Sdim 149234285Sdim if (SESS_LEADER(p)) { 150234285Sdim register struct session *sp = p->p_session; 151234285Sdim 152234285Sdim if (sp->s_ttyvp) { 153234285Sdim /* 154234285Sdim * Controlling process. 155234285Sdim * Signal foreground pgrp, 156234285Sdim * drain controlling terminal 157234285Sdim * and revoke access to controlling terminal. 158234285Sdim */ 159234285Sdim if (sp->s_ttyp->t_session == sp) { 160234285Sdim if (sp->s_ttyp->t_pgrp) 161234285Sdim pgsignal(sp->s_ttyp->t_pgrp, SIGHUP, 1); 162234285Sdim (void) ttywait(sp->s_ttyp); 163234285Sdim /* 164234285Sdim * The tty could have been revoked 165234285Sdim * if we blocked. 166234285Sdim */ 167234285Sdim if (sp->s_ttyvp) 168234285Sdim vgoneall(sp->s_ttyvp); 169234285Sdim } 170234285Sdim if (sp->s_ttyvp) 171234285Sdim vrele(sp->s_ttyvp); 172234285Sdim sp->s_ttyvp = NULL; 173234285Sdim /* 174234285Sdim * s_ttyp is not zero'd; we use this to indicate 175234285Sdim * that the session once had a controlling terminal. 176239462Sdim * (for logging and informational purposes) 177239462Sdim */ 178234285Sdim } 179234285Sdim sp->s_leader = NULL; 180239462Sdim } 181249423Sdim fixjobc(p, p->p_pgrp, 0); 182251662Sdim p->p_rlimit[RLIMIT_FSIZE].rlim_cur = RLIM_INFINITY; 183249423Sdim (void)acct_process(p); 184263508Sdim#ifdef KTRACE 185263508Sdim /* 186263508Sdim * release trace file 187263508Sdim */ 188263508Sdim p->p_traceflag = 0; /* don't trace the vrele() */ 189263508Sdim if (p->p_tracep) 190234285Sdim vrele(p->p_tracep); 191234285Sdim#endif 192239462Sdim /* 193239462Sdim * Remove proc from allproc queue and pidhash chain. 194239462Sdim * Place onto zombproc. Unlink from parent's child list. 195239462Sdim */ 196263508Sdim if ((*p->p_prev = p->p_next)) 197239462Sdim p->p_next->p_prev = p->p_prev; 198239462Sdim if ((p->p_next = zombproc)) 199234285Sdim p->p_next->p_prev = &p->p_next; 200249423Sdim p->p_prev = &zombproc; 201249423Sdim zombproc = p; 202249423Sdim p->p_stat = SZOMB; 203251662Sdim 204251662Sdim for (pp = &pidhash[PIDHASH(p->p_pid)]; *pp; pp = &(*pp)->p_hash) 205249423Sdim if (*pp == p) { 206249423Sdim *pp = p->p_hash; 207249423Sdim goto done; 208249423Sdim } 209249423Sdim panic("exit"); 210249423Sdimdone: 211249423Sdim 212249423Sdim if (p->p_cptr) /* only need this if any child is S_ZOMB */ 213251662Sdim wakeup((caddr_t) initproc); 214251662Sdim for (q = p->p_cptr; q != NULL; q = nq) { 215251662Sdim nq = q->p_osptr; 216234285Sdim if (nq != NULL) 217234285Sdim nq->p_ysptr = NULL; 218234285Sdim if (initproc->p_cptr) 219234285Sdim initproc->p_cptr->p_ysptr = q; 220234285Sdim q->p_osptr = initproc->p_cptr; 221234285Sdim q->p_ysptr = NULL; 222234285Sdim initproc->p_cptr = q; 223234285Sdim 224 q->p_pptr = initproc; 225 /* 226 * Traced processes are killed 227 * since their existence means someone is screwing up. 228 */ 229 if (q->p_flag & P_TRACED) { 230 q->p_flag &= ~P_TRACED; 231 psignal(q, SIGKILL); 232 } 233 } 234 p->p_cptr = NULL; 235 236 /* 237 * Save exit status and final rusage info, adding in child rusage 238 * info and self times. 239 */ 240 p->p_xstat = rv; 241 *p->p_ru = p->p_stats->p_ru; 242 calcru(p, &p->p_ru->ru_utime, &p->p_ru->ru_stime, NULL); 243 ruadd(p->p_ru, &p->p_stats->p_cru); 244 245 /* 246 * Notify parent that we're gone. 247 */ 248 psignal(p->p_pptr, SIGCHLD); 249 wakeup((caddr_t)p->p_pptr); 250#if defined(tahoe) 251 /* move this to cpu_exit */ 252 p->p_addr->u_pcb.pcb_savacc.faddr = (float *)NULL; 253#endif 254 /* 255 * Clear curproc after we've done all operations 256 * that could block, and before tearing down the rest 257 * of the process state that might be used from clock, etc. 258 * Also, can't clear curproc while we're still runnable, 259 * as we're not on a run queue (we are current, just not 260 * a proper proc any longer!). 261 * 262 * Other substructures are freed from wait(). 263 */ 264 curproc = NULL; 265 if (--p->p_limit->p_refcnt == 0) 266 FREE(p->p_limit, M_SUBPROC); 267 268 /* 269 * Finally, call machine-dependent code to release the remaining 270 * resources including address space, the kernel stack and pcb. 271 * The address space is released by "vmspace_free(p->p_vmspace)"; 272 * This is machine-dependent, as we may have to change stacks 273 * or ensure that the current one isn't reallocated before we 274 * finish. cpu_exit will end with a call to cpu_swtch(), finishing 275 * our execution (pun intended). 276 */ 277 cpu_exit(p); 278} 279 280struct wait_args { 281 int pid; 282 int *status; 283 int options; 284 struct rusage *rusage; 285#if defined(COMPAT_43) || defined(IBCS2) 286 int compat; /* pseudo */ 287#endif 288}; 289 290#if defined(COMPAT_43) || defined(IBCS2) 291#if defined(hp300) || defined(luna68k) 292#include <machine/frame.h> 293#define GETPS(rp) ((struct frame *)(rp))->f_sr 294#else 295#define GETPS(rp) (rp)[PS] 296#endif 297 298int 299owait(p, uap, retval) 300 struct proc *p; 301 register struct wait_args *uap; 302 int *retval; 303{ 304 305#ifdef PSL_ALLCC 306 if ((GETPS(p->p_md.md_regs) & PSL_ALLCC) != PSL_ALLCC) { 307 uap->options = 0; 308 uap->rusage = NULL; 309 } else { 310 uap->options = p->p_md.md_regs[R0]; 311 uap->rusage = (struct rusage *)p->p_md.md_regs[R1]; 312 } 313#else 314 uap->options = 0; 315 uap->rusage = NULL; 316#endif 317 uap->pid = WAIT_ANY; 318 uap->status = NULL; 319 uap->compat = 1; 320 return (wait1(p, uap, retval)); 321} 322 323int 324wait4(p, uap, retval) 325 struct proc *p; 326 struct wait_args *uap; 327 int *retval; 328{ 329 330 uap->compat = 0; 331 return (wait1(p, uap, retval)); 332} 333#else 334#define wait1 wait4 335#endif 336 337int 338wait1(q, uap, retval) 339 register struct proc *q; 340 register struct wait_args *uap; 341 int retval[]; 342{ 343 register int nfound; 344 register struct proc *p, *t; 345 int status, error, sig; 346 347 if (uap->pid == 0) 348 uap->pid = -q->p_pgid; 349#ifdef notyet 350 if (uap->options &~ (WUNTRACED|WNOHANG)) 351 return (EINVAL); 352#endif 353loop: 354 nfound = 0; 355 for (p = q->p_cptr; p; p = p->p_osptr) { 356 if (uap->pid != WAIT_ANY && 357 p->p_pid != uap->pid && p->p_pgid != -uap->pid) 358 continue; 359 nfound++; 360#if defined(COMPAT_43) || defined(IBCS2) 361 if (q->p_sysent->sv_sigtbl) { 362 if (p->p_xstat > q->p_sysent->sv_sigsize) 363 sig = q->p_sysent->sv_sigsize + 1; 364 else 365 sig = q->p_sysent->sv_sigtbl[p->p_xstat]; 366 } else 367 sig = p->p_xstat; 368#endif 369 if (p->p_stat == SZOMB) { 370 /* charge childs scheduling cpu usage to parent */ 371 if (curproc->p_pid != 1) { 372 curproc->p_estcpu = min(curproc->p_estcpu + 373 p->p_estcpu, UCHAR_MAX); 374 } 375 376 retval[0] = p->p_pid; 377#if defined(COMPAT_43) || defined(IBCS2) 378 if (uap->compat) 379 retval[1] = sig; 380 else 381#endif 382 if (uap->status) { 383 status = p->p_xstat; /* convert to int */ 384 if ((error = copyout((caddr_t)&status, 385 (caddr_t)uap->status, sizeof(status)))) 386 return (error); 387 } 388 if (uap->rusage && (error = copyout((caddr_t)p->p_ru, 389 (caddr_t)uap->rusage, sizeof (struct rusage)))) 390 return (error); 391 /* 392 * If we got the child via a ptrace 'attach', 393 * we need to give it back to the old parent. 394 */ 395 if (p->p_oppid && (t = pfind(p->p_oppid))) { 396 p->p_oppid = 0; 397 proc_reparent(p, t); 398 psignal(t, SIGCHLD); 399 wakeup((caddr_t)t); 400 return (0); 401 } 402 p->p_xstat = 0; 403 ruadd(&q->p_stats->p_cru, p->p_ru); 404 FREE(p->p_ru, M_ZOMBIE); 405 406 /* 407 * Decrement the count of procs running with this uid. 408 */ 409 (void)chgproccnt(p->p_cred->p_ruid, -1); 410 411 /* 412 * Free up credentials. 413 */ 414 if (--p->p_cred->p_refcnt == 0) { 415 crfree(p->p_cred->pc_ucred); 416 FREE(p->p_cred, M_SUBPROC); 417 } 418 419 /* 420 * Release reference to text vnode 421 */ 422 if (p->p_textvp) 423 vrele(p->p_textvp); 424 425 /* 426 * Finally finished with old proc entry. 427 * Unlink it from its process group and free it. 428 */ 429 leavepgrp(p); 430 if ((*p->p_prev = p->p_next)) /* off zombproc */ 431 p->p_next->p_prev = p->p_prev; 432 if ((q = p->p_ysptr)) 433 q->p_osptr = p->p_osptr; 434 if ((q = p->p_osptr)) 435 q->p_ysptr = p->p_ysptr; 436 if ((q = p->p_pptr)->p_cptr == p) 437 q->p_cptr = p->p_osptr; 438 439 /* 440 * Give machine-dependent layer a chance 441 * to free anything that cpu_exit couldn't 442 * release while still running in process context. 443 */ 444 cpu_wait(p); 445 FREE(p, M_PROC); 446 nprocs--; 447 return (0); 448 } 449 if (p->p_stat == SSTOP && (p->p_flag & P_WAITED) == 0 && 450 (p->p_flag & P_TRACED || uap->options & WUNTRACED)) { 451 p->p_flag |= P_WAITED; 452 retval[0] = p->p_pid; 453#if defined(COMPAT_43) || defined(IBCS2) 454 if (uap->compat) { 455 retval[1] = W_STOPCODE(sig); 456 error = 0; 457 } else 458#endif 459 if (uap->status) { 460 status = W_STOPCODE(p->p_xstat); 461 error = copyout((caddr_t)&status, 462 (caddr_t)uap->status, sizeof(status)); 463 } else 464 error = 0; 465 return (error); 466 } 467 } 468 if (nfound == 0) 469 return (ECHILD); 470 if (uap->options & WNOHANG) { 471 retval[0] = 0; 472 return (0); 473 } 474 if ((error = tsleep((caddr_t)q, PWAIT | PCATCH, "wait", 0))) 475 return (error); 476 goto loop; 477} 478 479/* 480 * make process 'parent' the new parent of process 'child'. 481 */ 482void 483proc_reparent(child, parent) 484 register struct proc *child; 485 register struct proc *parent; 486{ 487 register struct proc *o; 488 register struct proc *y; 489 490 if (child->p_pptr == parent) 491 return; 492 493 /* fix up the child linkage for the old parent */ 494 o = child->p_osptr; 495 y = child->p_ysptr; 496 if (y) 497 y->p_osptr = o; 498 if (o) 499 o->p_ysptr = y; 500 if (child->p_pptr->p_cptr == child) 501 child->p_pptr->p_cptr = o; 502 503 /* fix up child linkage for new parent */ 504 o = parent->p_cptr; 505 if (o) 506 o->p_ysptr = child; 507 child->p_osptr = o; 508 child->p_ysptr = NULL; 509 parent->p_cptr = child; 510 child->p_pptr = parent; 511} 512