|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1982, 1986, 1989 Regents of the University of California. ! 3: * All rights reserved. ! 4: * ! 5: * Redistribution is only permitted until one year after the first shipment ! 6: * of 4.4BSD by the Regents. Otherwise, redistribution and use in source and ! 7: * binary forms are permitted provided that: (1) source distributions retain ! 8: * this entire copyright notice and comment, and (2) distributions including ! 9: * binaries display the following acknowledgement: This product includes ! 10: * software developed by the University of California, Berkeley and its ! 11: * contributors'' in the documentation or other materials provided with the ! 12: * distribution and in all advertising materials mentioning features or use ! 13: * of this software. Neither the name of the University nor the names of ! 14: * its contributors may be used to endorse or promote products derived from ! 15: * this software without specific prior written permission. ! 16: * THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED ! 17: * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF ! 18: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ! 19: * ! 20: * @(#)kern_exit.c 7.26 (Berkeley) 6/28/90 ! 21: */ ! 22: ! 23: #include "param.h" ! 24: #include "systm.h" ! 25: #include "map.h" ! 26: #include "ioctl.h" ! 27: #include "tty.h" ! 28: #include "user.h" ! 29: #include "kernel.h" ! 30: #include "proc.h" ! 31: #include "buf.h" ! 32: #include "wait.h" ! 33: #include "vm.h" ! 34: #include "file.h" ! 35: #include "vnode.h" ! 36: #include "syslog.h" ! 37: #include "malloc.h" ! 38: ! 39: #include "machine/reg.h" ! 40: #ifdef COMPAT_43 ! 41: #include "machine/psl.h" ! 42: #endif ! 43: ! 44: /* ! 45: * Exit system call: pass back caller's arg ! 46: */ ! 47: /* ARGSUSED */ ! 48: rexit(p, uap, retval) ! 49: struct proc *p; ! 50: struct args { ! 51: int rval; ! 52: } *uap; ! 53: int *retval; ! 54: { ! 55: ! 56: return (exit(p, W_EXITCODE(uap->rval, 0))); ! 57: } ! 58: ! 59: /* ! 60: * Release resources. ! 61: * Save u. area for parent to look at. ! 62: * Enter zombie state. ! 63: * Wake up parent and init processes, ! 64: * and dispose of children. ! 65: */ ! 66: exit(p, rv) ! 67: struct proc *p; ! 68: int rv; ! 69: { ! 70: register int i; ! 71: register struct proc *q, *nq; ! 72: register struct proc **pp; ! 73: ! 74: #ifdef PGINPROF ! 75: vmsizmon(); ! 76: #endif ! 77: MALLOC(p->p_ru, struct rusage *, sizeof(struct rusage), ! 78: M_ZOMBIE, M_WAITOK); ! 79: p->p_flag &= ~(STRC|SULOCK); ! 80: p->p_flag |= SWEXIT; ! 81: p->p_sigignore = ~0; ! 82: p->p_sig = 0; ! 83: p->p_cpticks = 0; ! 84: p->p_pctcpu = 0; ! 85: for (i = 0; i < NSIG; i++) ! 86: u.u_signal[i] = SIG_IGN; ! 87: untimeout(realitexpire, (caddr_t)p); ! 88: /* ! 89: * Release virtual memory. If we resulted from ! 90: * a vfork(), instead give the resources back to ! 91: * the parent. ! 92: */ ! 93: if ((p->p_flag & SVFORK) == 0) { ! 94: #ifdef MAPMEM ! 95: if (u.u_mmap) ! 96: (void) mmexit(p); ! 97: #endif ! 98: vrelvm(); ! 99: } else { ! 100: p->p_flag &= ~SVFORK; ! 101: wakeup((caddr_t)p); ! 102: while ((p->p_flag & SVFDONE) == 0) ! 103: sleep((caddr_t)p, PZERO - 1); ! 104: p->p_flag &= ~SVFDONE; ! 105: } ! 106: for (i = 0; i <= u.u_lastfile; i++) { ! 107: struct file *f; ! 108: ! 109: f = u.u_ofile[i]; ! 110: if (f) { ! 111: u.u_ofile[i] = NULL; ! 112: u.u_pofile[i] = 0; ! 113: (void) closef(f); ! 114: } ! 115: } ! 116: if (SESS_LEADER(p)) { ! 117: register struct session *sp = p->p_session; ! 118: ! 119: if (sp->s_ttyvp) { ! 120: /* ! 121: * Controlling process. ! 122: * Signal foreground pgrp and revoke access ! 123: * to controlling terminal. ! 124: */ ! 125: if (sp->s_ttyp->t_pgrp) ! 126: pgsignal(sp->s_ttyp->t_pgrp, SIGHUP, 1); ! 127: vgoneall(sp->s_ttyvp); ! 128: vrele(sp->s_ttyvp); ! 129: sp->s_ttyvp = NULL; ! 130: /* ! 131: * s_ttyp is not zero'd; we use this to indicate ! 132: * that the session once had a controlling terminal. ! 133: * (for logging and informational purposes) ! 134: */ ! 135: } ! 136: sp->s_leader = 0; ! 137: } ! 138: VOP_LOCK(u.u_cdir); ! 139: vput(u.u_cdir); ! 140: if (u.u_rdir) { ! 141: VOP_LOCK(u.u_rdir); ! 142: vput(u.u_rdir); ! 143: } ! 144: u.u_rlimit[RLIMIT_FSIZE].rlim_cur = RLIM_INFINITY; ! 145: (void) acct(p); ! 146: crfree(u.u_cred); ! 147: #ifdef KTRACE ! 148: /* ! 149: * release trace file ! 150: */ ! 151: if (p->p_tracep) ! 152: vrele(p->p_tracep); ! 153: #endif ! 154: /* ! 155: * Freeing the user structure and kernel stack ! 156: * for the current process: have to run a bit longer ! 157: * using the pages which are about to be freed... ! 158: * vrelu will block memory allocation by raising ipl. ! 159: */ ! 160: vrelu(p, 0); ! 161: vrelpt(p); ! 162: if (*p->p_prev = p->p_nxt) /* off allproc queue */ ! 163: p->p_nxt->p_prev = p->p_prev; ! 164: if (p->p_nxt = zombproc) /* onto zombproc */ ! 165: p->p_nxt->p_prev = &p->p_nxt; ! 166: p->p_prev = &zombproc; ! 167: zombproc = p; ! 168: multprog--; ! 169: p->p_stat = SZOMB; ! 170: noproc = 1; ! 171: for (pp = &pidhash[PIDHASH(p->p_pid)]; *pp; pp = &(*pp)->p_hash) ! 172: if (*pp == p) { ! 173: *pp = p->p_hash; ! 174: goto done; ! 175: } ! 176: panic("exit"); ! 177: done: ! 178: if (p->p_pid == 1) { ! 179: if (p->p_dsize == 0) { ! 180: printf("Can't exec init (errno %d)\n", WEXITSTATUS(rv)); ! 181: for (;;) ! 182: ; ! 183: } else ! 184: panic("init died"); ! 185: } ! 186: p->p_xstat = rv; ! 187: *p->p_ru = u.u_ru; ! 188: i = splclock(); ! 189: p->p_ru->ru_stime = p->p_stime; ! 190: p->p_ru->ru_utime = p->p_utime; ! 191: splx(i); ! 192: ruadd(p->p_ru, &u.u_cru); ! 193: if (p->p_cptr) /* only need this if any child is S_ZOMB */ ! 194: wakeup((caddr_t)&proc[1]); ! 195: fixjobc(p, 0); ! 196: for (q = p->p_cptr; q != NULL; q = nq) { ! 197: nq = q->p_osptr; ! 198: if (nq != NULL) ! 199: nq->p_ysptr = NULL; ! 200: if (proc[1].p_cptr) ! 201: proc[1].p_cptr->p_ysptr = q; ! 202: q->p_osptr = proc[1].p_cptr; ! 203: q->p_ysptr = NULL; ! 204: proc[1].p_cptr = q; ! 205: ! 206: q->p_pptr = &proc[1]; ! 207: q->p_ppid = 1; ! 208: /* ! 209: * Traced processes are killed ! 210: * since their existence means someone is screwing up. ! 211: */ ! 212: if (q->p_flag&STRC) { ! 213: q->p_flag &= ~STRC; ! 214: psignal(q, SIGKILL); ! 215: } ! 216: } ! 217: p->p_cptr = NULL; ! 218: psignal(p->p_pptr, SIGCHLD); ! 219: wakeup((caddr_t)p->p_pptr); ! 220: #if defined(tahoe) ! 221: dkeyrelease(p->p_dkey), p->p_dkey = 0; ! 222: ckeyrelease(p->p_ckey), p->p_ckey = 0; ! 223: u.u_pcb.pcb_savacc.faddr = (float *)NULL; ! 224: #endif ! 225: swtch(); ! 226: } ! 227: ! 228: #ifdef COMPAT_43 ! 229: owait(p, uap, retval) ! 230: struct proc *p; ! 231: register struct args { ! 232: int pid; ! 233: int *status; ! 234: int options; ! 235: struct rusage *rusage; ! 236: int compat; ! 237: } *uap; ! 238: int *retval; ! 239: { ! 240: ! 241: if ((u.u_ar0[PS] & PSL_ALLCC) != PSL_ALLCC) { ! 242: uap->options = 0; ! 243: uap->rusage = 0; ! 244: } else { ! 245: uap->options = u.u_ar0[R0]; ! 246: uap->rusage = (struct rusage *)u.u_ar0[R1]; ! 247: } ! 248: uap->pid = WAIT_ANY; ! 249: uap->status = 0; ! 250: uap->compat = 1; ! 251: return (wait1(p, uap, retval)); ! 252: } ! 253: ! 254: wait4(p, uap, retval) ! 255: struct proc *p; ! 256: struct args { ! 257: int pid; ! 258: int *status; ! 259: int options; ! 260: struct rusage *rusage; ! 261: int compat; ! 262: } *uap; ! 263: int *retval; ! 264: { ! 265: ! 266: uap->compat = 0; ! 267: return (wait1(p, uap, retval)); ! 268: } ! 269: #else ! 270: #define wait1 wait4 ! 271: #endif ! 272: ! 273: /* ! 274: * Wait system call. ! 275: * Search for a terminated (zombie) child, ! 276: * finally lay it to rest, and collect its status. ! 277: * Look also for stopped (traced) children, ! 278: * and pass back status from them. ! 279: */ ! 280: wait1(q, uap, retval) ! 281: register struct proc *q; ! 282: register struct args { ! 283: int pid; ! 284: int *status; ! 285: int options; ! 286: struct rusage *rusage; ! 287: #ifdef COMPAT_43 ! 288: int compat; ! 289: #endif ! 290: } *uap; ! 291: int retval[]; ! 292: { ! 293: register int f; ! 294: register struct proc *p; ! 295: int status, error; ! 296: ! 297: if (uap->pid == 0) ! 298: uap->pid = -q->p_pgid; ! 299: #ifdef notyet ! 300: if (uap->options &~ (WUNTRACED|WNOHANG)) ! 301: return (EINVAL); ! 302: #endif ! 303: loop: ! 304: f = 0; ! 305: for (p = q->p_cptr; p; p = p->p_osptr) { ! 306: if (uap->pid != WAIT_ANY && ! 307: p->p_pid != uap->pid && p->p_pgid != -uap->pid) ! 308: continue; ! 309: f++; ! 310: if (p->p_stat == SZOMB) { ! 311: retval[0] = p->p_pid; ! 312: #ifdef COMPAT_43 ! 313: if (uap->compat) ! 314: retval[1] = p->p_xstat; ! 315: else ! 316: #endif ! 317: if (uap->status) { ! 318: status = p->p_xstat; /* convert to int */ ! 319: if (error = copyout((caddr_t)&status, ! 320: (caddr_t)uap->status, sizeof(status))) ! 321: return (error); ! 322: } ! 323: if (uap->rusage && (error = copyout((caddr_t)p->p_ru, ! 324: (caddr_t)uap->rusage, sizeof (struct rusage)))) ! 325: return (error); ! 326: pgrm(p); /* off pgrp */ ! 327: p->p_xstat = 0; ! 328: ruadd(&u.u_cru, p->p_ru); ! 329: FREE(p->p_ru, M_ZOMBIE); ! 330: p->p_ru = 0; ! 331: p->p_stat = NULL; ! 332: p->p_pid = 0; ! 333: p->p_ppid = 0; ! 334: if (*p->p_prev = p->p_nxt) /* off zombproc */ ! 335: p->p_nxt->p_prev = p->p_prev; ! 336: p->p_nxt = freeproc; /* onto freeproc */ ! 337: freeproc = p; ! 338: if (q = p->p_ysptr) ! 339: q->p_osptr = p->p_osptr; ! 340: if (q = p->p_osptr) ! 341: q->p_ysptr = p->p_ysptr; ! 342: if ((q = p->p_pptr)->p_cptr == p) ! 343: q->p_cptr = p->p_osptr; ! 344: p->p_pptr = 0; ! 345: p->p_ysptr = 0; ! 346: p->p_osptr = 0; ! 347: p->p_cptr = 0; ! 348: p->p_sig = 0; ! 349: p->p_sigcatch = 0; ! 350: p->p_sigignore = 0; ! 351: p->p_sigmask = 0; ! 352: /*p->p_pgrp = 0;*/ ! 353: p->p_flag = 0; ! 354: p->p_wchan = 0; ! 355: return (0); ! 356: } ! 357: if (p->p_stat == SSTOP && (p->p_flag & SWTED) == 0 && ! 358: (p->p_flag & STRC || uap->options & WUNTRACED)) { ! 359: p->p_flag |= SWTED; ! 360: retval[0] = p->p_pid; ! 361: #ifdef COMPAT_43 ! 362: if (uap->compat) { ! 363: retval[1] = W_STOPCODE(p->p_xstat); ! 364: error = 0; ! 365: } else ! 366: #endif ! 367: if (uap->status) { ! 368: status = W_STOPCODE(p->p_xstat); ! 369: error = copyout((caddr_t)&status, ! 370: (caddr_t)uap->status, sizeof(status)); ! 371: } else ! 372: error = 0; ! 373: return (error); ! 374: } ! 375: } ! 376: if (f == 0) ! 377: return (ECHILD); ! 378: if (uap->options & WNOHANG) { ! 379: retval[0] = 0; ! 380: return (0); ! 381: } ! 382: if (error = tsleep((caddr_t)q, PWAIT | PCATCH, "wait", 0)) ! 383: return (error); ! 384: goto loop; ! 385: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.