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