1 /* 2 * Copyright (c) 1982, 1986, 1989, 1991 Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 * 7 * @(#)kern_exit.c 7.34 (Berkeley) 05/12/91 8 */ 9 10 #include "param.h" 11 #include "systm.h" 12 #include "map.h" 13 #include "ioctl.h" 14 #include "tty.h" 15 #include "time.h" 16 #include "resource.h" 17 #include "kernel.h" 18 #include "proc.h" 19 #include "buf.h" 20 #include "wait.h" 21 #include "file.h" 22 #include "vnode.h" 23 #include "syslog.h" 24 #include "malloc.h" 25 #include "resourcevar.h" 26 27 #include "machine/cpu.h" 28 #ifdef COMPAT_43 29 #include "machine/reg.h" 30 #include "machine/psl.h" 31 #endif 32 33 #include "vm/vm.h" 34 #include "vm/vm_kern.h" 35 36 /* 37 * Exit system call: pass back caller's arg 38 */ 39 /* ARGSUSED */ 40 rexit(p, uap, retval) 41 struct proc *p; 42 struct args { 43 int rval; 44 } *uap; 45 int *retval; 46 { 47 48 exit(p, W_EXITCODE(uap->rval, 0)); 49 /* NOTREACHED */ 50 } 51 52 /* 53 * Exit: deallocate address space and other resources, 54 * change proc state to zombie, and unlink proc from allproc 55 * and parent's lists. Save exit status and rusage for wait(). 56 * Check for child processes and orphan them. 57 */ 58 exit(p, rv) 59 register struct proc *p; 60 int rv; 61 { 62 register struct proc *q, *nq; 63 register struct proc **pp; 64 int s; 65 66 #ifdef PGINPROF 67 vmsizmon(); 68 #endif 69 MALLOC(p->p_ru, struct rusage *, sizeof(struct rusage), 70 M_ZOMBIE, M_WAITOK); 71 /* 72 * If parent is waiting for us to exit or exec, 73 * SPPWAIT is set; we will wakeup the parent below. 74 */ 75 p->p_flag &= ~(STRC|SPPWAIT); 76 p->p_flag |= SWEXIT; 77 p->p_sigignore = ~0; 78 p->p_sig = 0; 79 untimeout(realitexpire, (caddr_t)p); 80 81 /* 82 * Close open files and release open-file table. 83 * This may block! 84 */ 85 fdfree(p); 86 #ifdef SYSVSHM 87 if (p->p_vmspace->vm_shm) 88 shmexit(p); 89 #endif 90 91 if (p->p_pid == 1) 92 panic("init died"); 93 if (SESS_LEADER(p)) { 94 register struct session *sp = p->p_session; 95 96 if (sp->s_ttyvp) { 97 /* 98 * Controlling process. 99 * Signal foreground pgrp, 100 * drain controlling terminal 101 * and revoke access to controlling terminal. 102 */ 103 if (sp->s_ttyp->t_session == sp) { 104 if (sp->s_ttyp->t_pgrp) 105 pgsignal(sp->s_ttyp->t_pgrp, SIGHUP, 1); 106 (void) ttywait(sp->s_ttyp); 107 vgoneall(sp->s_ttyvp); 108 } 109 vrele(sp->s_ttyvp); 110 sp->s_ttyvp = NULL; 111 /* 112 * s_ttyp is not zero'd; we use this to indicate 113 * that the session once had a controlling terminal. 114 * (for logging and informational purposes) 115 */ 116 } 117 sp->s_leader = NULL; 118 } 119 fixjobc(p, p->p_pgrp, 0); 120 p->p_rlimit[RLIMIT_FSIZE].rlim_cur = RLIM_INFINITY; 121 (void) acct(p); 122 if (--p->p_limit->p_refcnt == 0) 123 FREE(p->p_limit, M_SUBPROC); 124 if (--p->p_cred->p_refcnt == 0) { 125 crfree(p->p_cred->pc_ucred); 126 FREE(p->p_cred, M_SUBPROC); 127 } 128 #ifdef KTRACE 129 /* 130 * release trace file 131 */ 132 if (p->p_tracep) 133 vrele(p->p_tracep); 134 #endif 135 136 /* 137 * Remove proc from allproc queue and pidhash chain. 138 * Place onto zombproc. Unlink from parent's child list. 139 */ 140 if (*p->p_prev = p->p_nxt) 141 p->p_nxt->p_prev = p->p_prev; 142 if (p->p_nxt = zombproc) 143 p->p_nxt->p_prev = &p->p_nxt; 144 p->p_prev = &zombproc; 145 zombproc = p; 146 p->p_stat = SZOMB; 147 curproc = NULL; 148 for (pp = &pidhash[PIDHASH(p->p_pid)]; *pp; pp = &(*pp)->p_hash) 149 if (*pp == p) { 150 *pp = p->p_hash; 151 goto done; 152 } 153 panic("exit"); 154 done: 155 156 if (p->p_cptr) /* only need this if any child is S_ZOMB */ 157 wakeup((caddr_t) initproc); 158 for (q = p->p_cptr; q != NULL; q = nq) { 159 nq = q->p_osptr; 160 if (nq != NULL) 161 nq->p_ysptr = NULL; 162 if (initproc->p_cptr) 163 initproc->p_cptr->p_ysptr = q; 164 q->p_osptr = initproc->p_cptr; 165 q->p_ysptr = NULL; 166 initproc->p_cptr = q; 167 168 q->p_pptr = initproc; 169 /* 170 * Traced processes are killed 171 * since their existence means someone is screwing up. 172 */ 173 if (q->p_flag&STRC) { 174 q->p_flag &= ~STRC; 175 psignal(q, SIGKILL); 176 } 177 } 178 p->p_cptr = NULL; 179 180 /* 181 * Save exit status and final rusage info, 182 * adding in child rusage info and self times. 183 */ 184 p->p_xstat = rv; 185 *p->p_ru = p->p_stats->p_ru; 186 p->p_ru->ru_stime = p->p_stime; 187 p->p_ru->ru_utime = p->p_utime; 188 ruadd(p->p_ru, &p->p_stats->p_cru); 189 190 /* 191 * Notify parent that we're gone. 192 */ 193 psignal(p->p_pptr, SIGCHLD); 194 wakeup((caddr_t)p->p_pptr); 195 #if defined(tahoe) 196 /* move this to cpu_exit */ 197 p->p_addr->u_pcb.pcb_savacc.faddr = (float *)NULL; 198 #endif 199 /* 200 * Finally, call machine-dependent code to release the remaining 201 * resources including address space, the kernel stack and pcb. 202 * The address space is released by "vmspace_free(p->p_vmspace)"; 203 * This is machine-dependent, as we may have to change stacks 204 * or ensure that the current one isn't reallocated before we 205 * finish. cpu_exit will end with a call to swtch(), finishing 206 * our execution (pun intended). 207 */ 208 cpu_exit(p); 209 /* NOTREACHED */ 210 } 211 212 #ifdef COMPAT_43 213 owait(p, uap, retval) 214 struct proc *p; 215 register struct args { 216 int pid; 217 int *status; 218 int options; 219 struct rusage *rusage; 220 int compat; 221 } *uap; 222 int *retval; 223 { 224 225 if ((p->p_regs[PS] & PSL_ALLCC) != PSL_ALLCC) { 226 uap->options = 0; 227 uap->rusage = 0; 228 } else { 229 uap->options = p->p_regs[R0]; 230 uap->rusage = (struct rusage *)p->p_regs[R1]; 231 } 232 uap->pid = WAIT_ANY; 233 uap->status = 0; 234 uap->compat = 1; 235 return (wait1(p, uap, retval)); 236 } 237 238 wait4(p, uap, retval) 239 struct proc *p; 240 struct args { 241 int pid; 242 int *status; 243 int options; 244 struct rusage *rusage; 245 int compat; 246 } *uap; 247 int *retval; 248 { 249 250 uap->compat = 0; 251 return (wait1(p, uap, retval)); 252 } 253 #else 254 #define wait1 wait4 255 #endif 256 257 /* 258 * Wait: check child processes to see if any have exited, 259 * stopped under trace, or (optionally) stopped by a signal. 260 * Pass back status and deallocate exited child's proc structure. 261 */ 262 wait1(q, uap, retval) 263 register struct proc *q; 264 register struct args { 265 int pid; 266 int *status; 267 int options; 268 struct rusage *rusage; 269 #ifdef COMPAT_43 270 int compat; 271 #endif 272 } *uap; 273 int retval[]; 274 { 275 register int nfound; 276 register struct proc *p; 277 int status, error; 278 279 if (uap->pid == 0) 280 uap->pid = -q->p_pgid; 281 #ifdef notyet 282 if (uap->options &~ (WUNTRACED|WNOHANG)) 283 return (EINVAL); 284 #endif 285 loop: 286 nfound = 0; 287 for (p = q->p_cptr; p; p = p->p_osptr) { 288 if (uap->pid != WAIT_ANY && 289 p->p_pid != uap->pid && p->p_pgid != -uap->pid) 290 continue; 291 nfound++; 292 if (p->p_stat == SZOMB) { 293 retval[0] = p->p_pid; 294 #ifdef COMPAT_43 295 if (uap->compat) 296 retval[1] = p->p_xstat; 297 else 298 #endif 299 if (uap->status) { 300 status = p->p_xstat; /* convert to int */ 301 if (error = copyout((caddr_t)&status, 302 (caddr_t)uap->status, sizeof(status))) 303 return (error); 304 } 305 if (uap->rusage && (error = copyout((caddr_t)p->p_ru, 306 (caddr_t)uap->rusage, sizeof (struct rusage)))) 307 return (error); 308 p->p_xstat = 0; 309 ruadd(&q->p_stats->p_cru, p->p_ru); 310 FREE(p->p_ru, M_ZOMBIE); 311 312 /* 313 * Finally finished with old proc entry. 314 * Unlink it from its process group and free it. 315 */ 316 leavepgrp(p); 317 if (*p->p_prev = p->p_nxt) /* off zombproc */ 318 p->p_nxt->p_prev = p->p_prev; 319 if (q = p->p_ysptr) 320 q->p_osptr = p->p_osptr; 321 if (q = p->p_osptr) 322 q->p_ysptr = p->p_ysptr; 323 if ((q = p->p_pptr)->p_cptr == p) 324 q->p_cptr = p->p_osptr; 325 326 #ifdef i386 327 cpu_wait(p); /* XXX */ 328 #endif 329 330 FREE(p, M_PROC); 331 nprocs--; 332 return (0); 333 } 334 if (p->p_stat == SSTOP && (p->p_flag & SWTED) == 0 && 335 (p->p_flag & STRC || uap->options & WUNTRACED)) { 336 p->p_flag |= SWTED; 337 retval[0] = p->p_pid; 338 #ifdef COMPAT_43 339 if (uap->compat) { 340 retval[1] = W_STOPCODE(p->p_xstat); 341 error = 0; 342 } else 343 #endif 344 if (uap->status) { 345 status = W_STOPCODE(p->p_xstat); 346 error = copyout((caddr_t)&status, 347 (caddr_t)uap->status, sizeof(status)); 348 } else 349 error = 0; 350 return (error); 351 } 352 } 353 if (nfound == 0) 354 return (ECHILD); 355 if (uap->options & WNOHANG) { 356 retval[0] = 0; 357 return (0); 358 } 359 if (error = tsleep((caddr_t)q, PWAIT | PCATCH, "wait", 0)) 360 return (error); 361 goto loop; 362 } 363