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.41 (Berkeley) 02/14/92 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 87 /* The next two chunks should probably be moved to vmspace_exit. */ 88 #ifdef SYSVSHM 89 if (p->p_vmspace->vm_shm) 90 shmexit(p); 91 #endif 92 /* 93 * Release user portion of address space. 94 * This releases references to vnodes, 95 * which could cause I/O if the file has been unlinked. 96 * Need to do this early enough that we can still sleep. 97 * Can't free the entire vmspace as the kernel stack 98 * may be mapped within that space also. 99 */ 100 if (p->p_vmspace->vm_refcnt == 1) 101 (void) vm_map_remove(&p->p_vmspace->vm_map, VM_MIN_ADDRESS, 102 VM_MAXUSER_ADDRESS); 103 104 if (p->p_pid == 1) 105 panic("init died"); 106 if (SESS_LEADER(p)) { 107 register struct session *sp = p->p_session; 108 109 if (sp->s_ttyvp) { 110 /* 111 * Controlling process. 112 * Signal foreground pgrp, 113 * drain controlling terminal 114 * and revoke access to controlling terminal. 115 */ 116 if (sp->s_ttyp->t_session == sp) { 117 if (sp->s_ttyp->t_pgrp) 118 pgsignal(sp->s_ttyp->t_pgrp, SIGHUP, 1); 119 (void) ttywait(sp->s_ttyp); 120 vgoneall(sp->s_ttyvp); 121 } 122 vrele(sp->s_ttyvp); 123 sp->s_ttyvp = NULL; 124 /* 125 * s_ttyp is not zero'd; we use this to indicate 126 * that the session once had a controlling terminal. 127 * (for logging and informational purposes) 128 */ 129 } 130 sp->s_leader = NULL; 131 } 132 fixjobc(p, p->p_pgrp, 0); 133 p->p_rlimit[RLIMIT_FSIZE].rlim_cur = RLIM_INFINITY; 134 (void) acct(p); 135 #ifdef KTRACE 136 /* 137 * release trace file 138 */ 139 p->p_traceflag = 0; /* don't trace the vrele() */ 140 if (p->p_tracep) 141 vrele(p->p_tracep); 142 #endif 143 /* 144 * Remove proc from allproc queue and pidhash chain. 145 * Place onto zombproc. Unlink from parent's child list. 146 */ 147 if (*p->p_prev = p->p_nxt) 148 p->p_nxt->p_prev = p->p_prev; 149 if (p->p_nxt = zombproc) 150 p->p_nxt->p_prev = &p->p_nxt; 151 p->p_prev = &zombproc; 152 zombproc = p; 153 p->p_stat = SZOMB; 154 155 for (pp = &pidhash[PIDHASH(p->p_pid)]; *pp; pp = &(*pp)->p_hash) 156 if (*pp == p) { 157 *pp = p->p_hash; 158 goto done; 159 } 160 panic("exit"); 161 done: 162 163 if (p->p_cptr) /* only need this if any child is S_ZOMB */ 164 wakeup((caddr_t) initproc); 165 for (q = p->p_cptr; q != NULL; q = nq) { 166 nq = q->p_osptr; 167 if (nq != NULL) 168 nq->p_ysptr = NULL; 169 if (initproc->p_cptr) 170 initproc->p_cptr->p_ysptr = q; 171 q->p_osptr = initproc->p_cptr; 172 q->p_ysptr = NULL; 173 initproc->p_cptr = q; 174 175 q->p_pptr = initproc; 176 /* 177 * Traced processes are killed 178 * since their existence means someone is screwing up. 179 */ 180 if (q->p_flag&STRC) { 181 q->p_flag &= ~STRC; 182 psignal(q, SIGKILL); 183 } 184 } 185 p->p_cptr = NULL; 186 187 /* 188 * Save exit status and final rusage info, 189 * adding in child rusage info and self times. 190 */ 191 p->p_xstat = rv; 192 *p->p_ru = p->p_stats->p_ru; 193 p->p_ru->ru_stime = p->p_stime; 194 p->p_ru->ru_utime = p->p_utime; 195 ruadd(p->p_ru, &p->p_stats->p_cru); 196 197 /* 198 * Notify parent that we're gone. 199 */ 200 psignal(p->p_pptr, SIGCHLD); 201 wakeup((caddr_t)p->p_pptr); 202 #if defined(tahoe) 203 /* move this to cpu_exit */ 204 p->p_addr->u_pcb.pcb_savacc.faddr = (float *)NULL; 205 #endif 206 /* 207 * Clear curproc after we've done all operations 208 * that could block, and before tearing down the rest 209 * of the process state that might be used from clock, etc. 210 * Also, can't clear curproc while we're still runnable, 211 * as we're not on a run queue (we are current, just not 212 * a proper proc any longer!). 213 * 214 * Other substructures are freed from wait(). 215 */ 216 curproc = NULL; 217 if (--p->p_limit->p_refcnt == 0) 218 FREE(p->p_limit, M_SUBPROC); 219 220 /* 221 * Finally, call machine-dependent code to release the remaining 222 * resources including address space, the kernel stack and pcb. 223 * The address space is released by "vmspace_free(p->p_vmspace)"; 224 * This is machine-dependent, as we may have to change stacks 225 * or ensure that the current one isn't reallocated before we 226 * finish. cpu_exit will end with a call to swtch(), finishing 227 * our execution (pun intended). 228 */ 229 cpu_exit(p); 230 /* NOTREACHED */ 231 } 232 233 #ifdef COMPAT_43 234 owait(p, uap, retval) 235 struct proc *p; 236 register struct args { 237 int pid; 238 int *status; 239 int options; 240 struct rusage *rusage; 241 int compat; 242 } *uap; 243 int *retval; 244 { 245 246 #ifdef PSL_ALLCC 247 if ((p->p_md.md_regs[PS] & PSL_ALLCC) != PSL_ALLCC) { 248 uap->options = 0; 249 uap->rusage = 0; 250 } else { 251 uap->options = p->p_md.md_regs[R0]; 252 uap->rusage = (struct rusage *)p->p_md.md_regs[R1]; 253 } 254 #else 255 uap->options = 0; 256 uap->rusage = 0; 257 #endif 258 uap->pid = WAIT_ANY; 259 uap->status = 0; 260 uap->compat = 1; 261 return (wait1(p, uap, retval)); 262 } 263 264 wait4(p, uap, retval) 265 struct proc *p; 266 struct args { 267 int pid; 268 int *status; 269 int options; 270 struct rusage *rusage; 271 int compat; 272 } *uap; 273 int *retval; 274 { 275 276 uap->compat = 0; 277 return (wait1(p, uap, retval)); 278 } 279 #else 280 #define wait1 wait4 281 #endif 282 283 /* 284 * Wait: check child processes to see if any have exited, 285 * stopped under trace, or (optionally) stopped by a signal. 286 * Pass back status and deallocate exited child's proc structure. 287 */ 288 wait1(q, uap, retval) 289 register struct proc *q; 290 register struct args { 291 int pid; 292 int *status; 293 int options; 294 struct rusage *rusage; 295 #ifdef COMPAT_43 296 int compat; 297 #endif 298 } *uap; 299 int retval[]; 300 { 301 register int nfound; 302 register struct proc *p; 303 int status, error; 304 305 if (uap->pid == 0) 306 uap->pid = -q->p_pgid; 307 #ifdef notyet 308 if (uap->options &~ (WUNTRACED|WNOHANG)) 309 return (EINVAL); 310 #endif 311 loop: 312 nfound = 0; 313 for (p = q->p_cptr; p; p = p->p_osptr) { 314 if (uap->pid != WAIT_ANY && 315 p->p_pid != uap->pid && p->p_pgid != -uap->pid) 316 continue; 317 nfound++; 318 if (p->p_stat == SZOMB) { 319 retval[0] = p->p_pid; 320 #ifdef COMPAT_43 321 if (uap->compat) 322 retval[1] = p->p_xstat; 323 else 324 #endif 325 if (uap->status) { 326 status = p->p_xstat; /* convert to int */ 327 if (error = copyout((caddr_t)&status, 328 (caddr_t)uap->status, sizeof(status))) 329 return (error); 330 } 331 if (uap->rusage && (error = copyout((caddr_t)p->p_ru, 332 (caddr_t)uap->rusage, sizeof (struct rusage)))) 333 return (error); 334 p->p_xstat = 0; 335 ruadd(&q->p_stats->p_cru, p->p_ru); 336 FREE(p->p_ru, M_ZOMBIE); 337 if (--p->p_cred->p_refcnt == 0) { 338 crfree(p->p_cred->pc_ucred); 339 FREE(p->p_cred, M_SUBPROC); 340 } 341 342 /* 343 * Finally finished with old proc entry. 344 * Unlink it from its process group and free it. 345 */ 346 leavepgrp(p); 347 if (*p->p_prev = p->p_nxt) /* off zombproc */ 348 p->p_nxt->p_prev = p->p_prev; 349 if (q = p->p_ysptr) 350 q->p_osptr = p->p_osptr; 351 if (q = p->p_osptr) 352 q->p_ysptr = p->p_ysptr; 353 if ((q = p->p_pptr)->p_cptr == p) 354 q->p_cptr = p->p_osptr; 355 356 /* 357 * Give machine-dependent layer a chance 358 * to free anything that cpu_exit couldn't 359 * release while still running in process context. 360 */ 361 cpu_wait(p); 362 FREE(p, M_PROC); 363 nprocs--; 364 return (0); 365 } 366 if (p->p_stat == SSTOP && (p->p_flag & SWTED) == 0 && 367 (p->p_flag & STRC || uap->options & WUNTRACED)) { 368 p->p_flag |= SWTED; 369 retval[0] = p->p_pid; 370 #ifdef COMPAT_43 371 if (uap->compat) { 372 retval[1] = W_STOPCODE(p->p_xstat); 373 error = 0; 374 } else 375 #endif 376 if (uap->status) { 377 status = W_STOPCODE(p->p_xstat); 378 error = copyout((caddr_t)&status, 379 (caddr_t)uap->status, sizeof(status)); 380 } else 381 error = 0; 382 return (error); 383 } 384 } 385 if (nfound == 0) 386 return (ECHILD); 387 if (uap->options & WNOHANG) { 388 retval[0] = 0; 389 return (0); 390 } 391 if (error = tsleep((caddr_t)q, PWAIT | PCATCH, "wait", 0)) 392 return (error); 393 goto loop; 394 } 395