|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1982, 1986, 1989, 1991 Regents of the University of California. ! 3: * All rights reserved. ! 4: * ! 5: * Redistribution and use in source and binary forms, with or without ! 6: * modification, are permitted provided that the following conditions ! 7: * are met: ! 8: * 1. Redistributions of source code must retain the above copyright ! 9: * notice, this list of conditions and the following disclaimer. ! 10: * 2. Redistributions in binary form must reproduce the above copyright ! 11: * notice, this list of conditions and the following disclaimer in the ! 12: * documentation and/or other materials provided with the distribution. ! 13: * 3. All advertising materials mentioning features or use of this software ! 14: * must display the following acknowledgement: ! 15: * This product includes software developed by the University of ! 16: * California, Berkeley and its contributors. ! 17: * 4. Neither the name of the University nor the names of its contributors ! 18: * may be used to endorse or promote products derived from this software ! 19: * without specific prior written permission. ! 20: * ! 21: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ! 22: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ! 23: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ! 24: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE ! 25: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ! 26: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ! 27: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ! 28: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ! 29: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ! 30: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ! 31: * SUCH DAMAGE. ! 32: * ! 33: * @(#)kern_exit.c 7.35 (Berkeley) 6/27/91 ! 34: */ ! 35: ! 36: #include "param.h" ! 37: #include "systm.h" ! 38: #include "map.h" ! 39: #include "ioctl.h" ! 40: #include "tty.h" ! 41: #include "time.h" ! 42: #include "resource.h" ! 43: #include "kernel.h" ! 44: #include "proc.h" ! 45: #include "buf.h" ! 46: #include "wait.h" ! 47: #include "file.h" ! 48: #include "vnode.h" ! 49: #include "syslog.h" ! 50: #include "malloc.h" ! 51: #include "resourcevar.h" ! 52: ! 53: #include "machine/cpu.h" ! 54: #ifdef COMPAT_43 ! 55: #include "machine/reg.h" ! 56: #include "machine/psl.h" ! 57: #endif ! 58: ! 59: #include "vm/vm.h" ! 60: #include "vm/vm_kern.h" ! 61: ! 62: /* ! 63: * Exit system call: pass back caller's arg ! 64: */ ! 65: /* ARGSUSED */ ! 66: rexit(p, uap, retval) ! 67: struct proc *p; ! 68: struct args { ! 69: int rval; ! 70: } *uap; ! 71: int *retval; ! 72: { ! 73: ! 74: exit(p, W_EXITCODE(uap->rval, 0)); ! 75: /* NOTREACHED */ ! 76: } ! 77: ! 78: /* ! 79: * Exit: deallocate address space and other resources, ! 80: * change proc state to zombie, and unlink proc from allproc ! 81: * and parent's lists. Save exit status and rusage for wait(). ! 82: * Check for child processes and orphan them. ! 83: */ ! 84: exit(p, rv) ! 85: register struct proc *p; ! 86: int rv; ! 87: { ! 88: register struct proc *q, *nq; ! 89: register struct proc **pp; ! 90: int s; ! 91: ! 92: #ifdef PGINPROF ! 93: vmsizmon(); ! 94: #endif ! 95: MALLOC(p->p_ru, struct rusage *, sizeof(struct rusage), ! 96: M_ZOMBIE, M_WAITOK); ! 97: /* ! 98: * If parent is waiting for us to exit or exec, ! 99: * SPPWAIT is set; we will wakeup the parent below. ! 100: */ ! 101: p->p_flag &= ~(STRC|SPPWAIT); ! 102: p->p_flag |= SWEXIT; ! 103: p->p_sigignore = ~0; ! 104: p->p_sig = 0; ! 105: untimeout(realitexpire, (caddr_t)p); ! 106: ! 107: /* ! 108: * Close open files and release open-file table. ! 109: * This may block! ! 110: */ ! 111: fdfree(p); ! 112: ! 113: /* The next two chunks should probably be moved to vmspace_exit. */ ! 114: #ifdef SYSVSHM ! 115: if (p->p_vmspace->vm_shm) ! 116: shmexit(p); ! 117: #endif ! 118: /* ! 119: * Release user portion of address space. ! 120: * This releases references to vnodes, ! 121: * which could cause I/O if the file has been unlinked. ! 122: * Need to do this early enough that we can still sleep. ! 123: * Can't free the entire vmspace as the kernel stack ! 124: * may be mapped within that space also. ! 125: */ ! 126: if (p->p_vmspace->vm_refcnt == 1) ! 127: (void) vm_map_remove(&p->p_vmspace->vm_map, VM_MIN_ADDRESS, ! 128: VM_MAXUSER_ADDRESS); ! 129: ! 130: if (p->p_pid == 1) ! 131: panic("init died"); ! 132: if (SESS_LEADER(p)) { ! 133: register struct session *sp = p->p_session; ! 134: ! 135: if (sp->s_ttyvp) { ! 136: /* ! 137: * Controlling process. ! 138: * Signal foreground pgrp, ! 139: * drain controlling terminal ! 140: * and revoke access to controlling terminal. ! 141: */ ! 142: if (sp->s_ttyp->t_session == sp) { ! 143: if (sp->s_ttyp->t_pgrp) ! 144: pgsignal(sp->s_ttyp->t_pgrp, SIGHUP, 1); ! 145: (void) ttywait(sp->s_ttyp); ! 146: vgoneall(sp->s_ttyvp); ! 147: } ! 148: vrele(sp->s_ttyvp); ! 149: sp->s_ttyvp = NULL; ! 150: /* ! 151: * s_ttyp is not zero'd; we use this to indicate ! 152: * that the session once had a controlling terminal. ! 153: * (for logging and informational purposes) ! 154: */ ! 155: } ! 156: sp->s_leader = NULL; ! 157: } ! 158: fixjobc(p, p->p_pgrp, 0); ! 159: p->p_rlimit[RLIMIT_FSIZE].rlim_cur = RLIM_INFINITY; ! 160: (void) acct(p); ! 161: if (--p->p_limit->p_refcnt == 0) ! 162: FREE(p->p_limit, M_SUBPROC); ! 163: #ifdef KTRACE ! 164: /* ! 165: * release trace file ! 166: */ ! 167: if (p->p_tracep) ! 168: vrele(p->p_tracep); ! 169: #endif ! 170: ! 171: /* ! 172: * Remove proc from allproc queue and pidhash chain. ! 173: * Place onto zombproc. Unlink from parent's child list. ! 174: */ ! 175: if (*p->p_prev = p->p_nxt) ! 176: p->p_nxt->p_prev = p->p_prev; ! 177: if (p->p_nxt = zombproc) ! 178: p->p_nxt->p_prev = &p->p_nxt; ! 179: p->p_prev = &zombproc; ! 180: zombproc = p; ! 181: p->p_stat = SZOMB; ! 182: curproc = NULL; ! 183: for (pp = &pidhash[PIDHASH(p->p_pid)]; *pp; pp = &(*pp)->p_hash) ! 184: if (*pp == p) { ! 185: *pp = p->p_hash; ! 186: goto done; ! 187: } ! 188: panic("exit"); ! 189: done: ! 190: ! 191: if (p->p_cptr) /* only need this if any child is S_ZOMB */ ! 192: wakeup((caddr_t) initproc); ! 193: for (q = p->p_cptr; q != NULL; q = nq) { ! 194: nq = q->p_osptr; ! 195: if (nq != NULL) ! 196: nq->p_ysptr = NULL; ! 197: if (initproc->p_cptr) ! 198: initproc->p_cptr->p_ysptr = q; ! 199: q->p_osptr = initproc->p_cptr; ! 200: q->p_ysptr = NULL; ! 201: initproc->p_cptr = q; ! 202: ! 203: q->p_pptr = initproc; ! 204: /* ! 205: * Traced processes are killed ! 206: * since their existence means someone is screwing up. ! 207: */ ! 208: if (q->p_flag&STRC) { ! 209: q->p_flag &= ~STRC; ! 210: psignal(q, SIGKILL); ! 211: } ! 212: } ! 213: p->p_cptr = NULL; ! 214: ! 215: /* ! 216: * Save exit status and final rusage info, ! 217: * adding in child rusage info and self times. ! 218: */ ! 219: p->p_xstat = rv; ! 220: *p->p_ru = p->p_stats->p_ru; ! 221: p->p_ru->ru_stime = p->p_stime; ! 222: p->p_ru->ru_utime = p->p_utime; ! 223: ruadd(p->p_ru, &p->p_stats->p_cru); ! 224: ! 225: /* ! 226: * Notify parent that we're gone. ! 227: */ ! 228: psignal(p->p_pptr, SIGCHLD); ! 229: wakeup((caddr_t)p->p_pptr); ! 230: #if defined(tahoe) ! 231: /* move this to cpu_exit */ ! 232: p->p_addr->u_pcb.pcb_savacc.faddr = (float *)NULL; ! 233: #endif ! 234: /* ! 235: * Finally, call machine-dependent code to release the remaining ! 236: * resources including address space, the kernel stack and pcb. ! 237: * The address space is released by "vmspace_free(p->p_vmspace)"; ! 238: * This is machine-dependent, as we may have to change stacks ! 239: * or ensure that the current one isn't reallocated before we ! 240: * finish. cpu_exit will end with a call to swtch(), finishing ! 241: * our execution (pun intended). ! 242: */ ! 243: cpu_exit(p); ! 244: /* NOTREACHED */ ! 245: } ! 246: ! 247: #ifdef COMPAT_43 ! 248: owait(p, uap, retval) ! 249: struct proc *p; ! 250: register struct args { ! 251: int pid; ! 252: int *status; ! 253: int options; ! 254: struct rusage *rusage; ! 255: int compat; ! 256: } *uap; ! 257: int *retval; ! 258: { ! 259: ! 260: if ((p->p_regs[PS] & PSL_ALLCC) != PSL_ALLCC) { ! 261: uap->options = 0; ! 262: uap->rusage = 0; ! 263: } else { ! 264: uap->options = p->p_regs[R0]; ! 265: uap->rusage = (struct rusage *)p->p_regs[R1]; ! 266: } ! 267: uap->pid = WAIT_ANY; ! 268: uap->status = 0; ! 269: uap->compat = 1; ! 270: return (wait1(p, uap, retval)); ! 271: } ! 272: ! 273: wait4(p, uap, retval) ! 274: struct proc *p; ! 275: struct args { ! 276: int pid; ! 277: int *status; ! 278: int options; ! 279: struct rusage *rusage; ! 280: int compat; ! 281: } *uap; ! 282: int *retval; ! 283: { ! 284: ! 285: uap->compat = 0; ! 286: return (wait1(p, uap, retval)); ! 287: } ! 288: #else ! 289: #define wait1 wait4 ! 290: #endif ! 291: ! 292: /* ! 293: * Wait: check child processes to see if any have exited, ! 294: * stopped under trace, or (optionally) stopped by a signal. ! 295: * Pass back status and deallocate exited child's proc structure. ! 296: */ ! 297: wait1(q, uap, retval) ! 298: register struct proc *q; ! 299: register struct args { ! 300: int pid; ! 301: int *status; ! 302: int options; ! 303: struct rusage *rusage; ! 304: #ifdef COMPAT_43 ! 305: int compat; ! 306: #endif ! 307: } *uap; ! 308: int retval[]; ! 309: { ! 310: register int nfound; ! 311: register struct proc *p; ! 312: int status, error; ! 313: ! 314: if (uap->pid == 0) ! 315: uap->pid = -q->p_pgid; ! 316: #ifdef notyet ! 317: if (uap->options &~ (WUNTRACED|WNOHANG)) ! 318: return (EINVAL); ! 319: #endif ! 320: loop: ! 321: nfound = 0; ! 322: for (p = q->p_cptr; p; p = p->p_osptr) { ! 323: if (uap->pid != WAIT_ANY && ! 324: p->p_pid != uap->pid && p->p_pgid != -uap->pid) ! 325: continue; ! 326: nfound++; ! 327: if (p->p_stat == SZOMB) { ! 328: retval[0] = p->p_pid; ! 329: #ifdef COMPAT_43 ! 330: if (uap->compat) ! 331: retval[1] = p->p_xstat; ! 332: else ! 333: #endif ! 334: if (uap->status) { ! 335: status = p->p_xstat; /* convert to int */ ! 336: if (error = copyout((caddr_t)&status, ! 337: (caddr_t)uap->status, sizeof(status))) ! 338: return (error); ! 339: } ! 340: if (uap->rusage && (error = copyout((caddr_t)p->p_ru, ! 341: (caddr_t)uap->rusage, sizeof (struct rusage)))) ! 342: return (error); ! 343: p->p_xstat = 0; ! 344: ruadd(&q->p_stats->p_cru, p->p_ru); ! 345: FREE(p->p_ru, M_ZOMBIE); ! 346: if (--p->p_cred->p_refcnt == 0) { ! 347: crfree(p->p_cred->pc_ucred); ! 348: FREE(p->p_cred, M_SUBPROC); ! 349: } ! 350: ! 351: /* ! 352: * Finally finished with old proc entry. ! 353: * Unlink it from its process group and free it. ! 354: */ ! 355: leavepgrp(p); ! 356: if (*p->p_prev = p->p_nxt) /* off zombproc */ ! 357: p->p_nxt->p_prev = p->p_prev; ! 358: if (q = p->p_ysptr) ! 359: q->p_osptr = p->p_osptr; ! 360: if (q = p->p_osptr) ! 361: q->p_ysptr = p->p_ysptr; ! 362: if ((q = p->p_pptr)->p_cptr == p) ! 363: q->p_cptr = p->p_osptr; ! 364: ! 365: /* ! 366: * Give machine-dependent layer a chance ! 367: * to free anything that cpu_exit couldn't ! 368: * release while still running in process context. ! 369: */ ! 370: cpu_wait(p); ! 371: FREE(p, M_PROC); ! 372: nprocs--; ! 373: return (0); ! 374: } ! 375: if (p->p_stat == SSTOP && (p->p_flag & SWTED) == 0 && ! 376: (p->p_flag & STRC || uap->options & WUNTRACED)) { ! 377: p->p_flag |= SWTED; ! 378: retval[0] = p->p_pid; ! 379: #ifdef COMPAT_43 ! 380: if (uap->compat) { ! 381: retval[1] = W_STOPCODE(p->p_xstat); ! 382: error = 0; ! 383: } else ! 384: #endif ! 385: if (uap->status) { ! 386: status = W_STOPCODE(p->p_xstat); ! 387: error = copyout((caddr_t)&status, ! 388: (caddr_t)uap->status, sizeof(status)); ! 389: } else ! 390: error = 0; ! 391: return (error); ! 392: } ! 393: } ! 394: if (nfound == 0) ! 395: return (ECHILD); ! 396: if (uap->options & WNOHANG) { ! 397: retval[0] = 0; ! 398: return (0); ! 399: } ! 400: if (error = tsleep((caddr_t)q, PWAIT | PCATCH, "wait", 0)) ! 401: return (error); ! 402: goto loop; ! 403: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.