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