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