1 /* 2 * Copyright (c) 1982, 1986, 1989 Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 * 7 * @(#)kern_exit.c 7.30 (Berkeley) 01/10/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 "user.h" 16 #include "kernel.h" 17 #include "proc.h" 18 #include "buf.h" 19 #include "wait.h" 20 #include "file.h" 21 #include "vnode.h" 22 #include "syslog.h" 23 #include "malloc.h" 24 25 #include "machine/reg.h" 26 #ifdef COMPAT_43 27 #include "machine/psl.h" 28 #endif 29 30 #include "../vm/vm_param.h" 31 #include "../vm/vm_map.h" 32 #include "../vm/vm_kern.h" 33 34 /* 35 * Exit system call: pass back caller's arg 36 */ 37 /* ARGSUSED */ 38 rexit(p, uap, retval) 39 struct proc *p; 40 struct args { 41 int rval; 42 } *uap; 43 int *retval; 44 { 45 46 exit(p, W_EXITCODE(uap->rval, 0)); 47 /* NOTREACHED */ 48 } 49 50 /* 51 * Release resources. 52 * Save u. area for parent to look at. 53 * Enter zombie state. 54 * Wake up parent and init processes, 55 * and dispose of children. 56 */ 57 exit(p, rv) 58 struct proc *p; 59 int rv; 60 { 61 register int i; 62 register struct proc *q, *nq; 63 register struct proc **pp; 64 65 #ifdef PGINPROF 66 vmsizmon(); 67 #endif 68 MALLOC(p->p_ru, struct rusage *, sizeof(struct rusage), 69 M_ZOMBIE, M_WAITOK); 70 p->p_flag &= ~(STRC|SULOCK); 71 p->p_flag |= SWEXIT; 72 p->p_sigignore = ~0; 73 p->p_sig = 0; 74 p->p_cpticks = 0; 75 p->p_pctcpu = 0; 76 for (i = 0; i < NSIG; i++) 77 u.u_signal[i] = SIG_IGN; 78 untimeout(realitexpire, (caddr_t)p); 79 #ifdef SYSVSHM 80 if (p->p_shm) 81 shmexit(p); 82 #endif 83 vm_map_deallocate(p->p_map); 84 p->p_map = VM_MAP_NULL; 85 /* 86 * XXX preserve synchronization semantics of vfork 87 */ 88 if (p->p_flag & SVFORK) { 89 p->p_flag &= ~SVFORK; 90 wakeup((caddr_t)p); 91 while ((p->p_flag & SVFDONE) == 0) 92 sleep((caddr_t)p, PZERO - 1); 93 p->p_flag &= ~SVFDONE; 94 } 95 fdrele(p->p_fd); 96 p->p_fd = (struct filedesc *)0; 97 if (SESS_LEADER(p)) { 98 register struct session *sp = p->p_session; 99 100 if (sp->s_ttyvp) { 101 /* 102 * Controlling process. 103 * Signal foreground pgrp and revoke access 104 * to controlling terminal. 105 */ 106 if (sp->s_ttyp->t_pgrp) 107 pgsignal(sp->s_ttyp->t_pgrp, SIGHUP, 1); 108 vgoneall(sp->s_ttyvp); 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 = 0; 118 } 119 u.u_rlimit[RLIMIT_FSIZE].rlim_cur = RLIM_INFINITY; 120 (void) acct(p); 121 crfree(u.u_cred); 122 #ifdef KTRACE 123 /* 124 * release trace file 125 */ 126 if (p->p_tracep) 127 vrele(p->p_tracep); 128 #endif 129 splimp(); 130 /* I don't think this will cause a sleep/realloc anywhere... */ 131 kmem_free(kernel_map, (vm_offset_t)p->p_addr, 132 round_page(ctob(UPAGES))); 133 if (*p->p_prev = p->p_nxt) /* off allproc queue */ 134 p->p_nxt->p_prev = p->p_prev; 135 if (p->p_nxt = zombproc) /* onto zombproc */ 136 p->p_nxt->p_prev = &p->p_nxt; 137 p->p_prev = &zombproc; 138 zombproc = p; 139 p->p_stat = SZOMB; 140 noproc = 1; 141 for (pp = &pidhash[PIDHASH(p->p_pid)]; *pp; pp = &(*pp)->p_hash) 142 if (*pp == p) { 143 *pp = p->p_hash; 144 goto done; 145 } 146 panic("exit"); 147 done: 148 if (p->p_pid == 1) 149 panic("init died"); 150 p->p_xstat = rv; 151 *p->p_ru = u.u_ru; 152 i = splclock(); 153 p->p_ru->ru_stime = p->p_stime; 154 p->p_ru->ru_utime = p->p_utime; 155 splx(i); 156 ruadd(p->p_ru, &u.u_cru); 157 if (p->p_cptr) /* only need this if any child is S_ZOMB */ 158 wakeup((caddr_t)&proc[1]); 159 fixjobc(p, p->p_pgrp, 0); 160 for (q = p->p_cptr; q != NULL; q = nq) { 161 nq = q->p_osptr; 162 if (nq != NULL) 163 nq->p_ysptr = NULL; 164 if (proc[1].p_cptr) 165 proc[1].p_cptr->p_ysptr = q; 166 q->p_osptr = proc[1].p_cptr; 167 q->p_ysptr = NULL; 168 proc[1].p_cptr = q; 169 170 q->p_pptr = &proc[1]; 171 q->p_ppid = 1; 172 /* 173 * Traced processes are killed 174 * since their existence means someone is screwing up. 175 */ 176 if (q->p_flag&STRC) { 177 q->p_flag &= ~STRC; 178 psignal(q, SIGKILL); 179 } 180 } 181 p->p_cptr = NULL; 182 psignal(p->p_pptr, SIGCHLD); 183 wakeup((caddr_t)p->p_pptr); 184 #if defined(tahoe) 185 dkeyrelease(p->p_dkey), p->p_dkey = 0; 186 ckeyrelease(p->p_ckey), p->p_ckey = 0; 187 u.u_pcb.pcb_savacc.faddr = (float *)NULL; 188 #endif 189 swtch(); 190 } 191 192 #ifdef COMPAT_43 193 owait(p, uap, retval) 194 struct proc *p; 195 register struct args { 196 int pid; 197 int *status; 198 int options; 199 struct rusage *rusage; 200 int compat; 201 } *uap; 202 int *retval; 203 { 204 205 if ((u.u_ar0[PS] & PSL_ALLCC) != PSL_ALLCC) { 206 uap->options = 0; 207 uap->rusage = 0; 208 } else { 209 uap->options = u.u_ar0[R0]; 210 uap->rusage = (struct rusage *)u.u_ar0[R1]; 211 } 212 uap->pid = WAIT_ANY; 213 uap->status = 0; 214 uap->compat = 1; 215 return (wait1(p, uap, retval)); 216 } 217 218 wait4(p, uap, retval) 219 struct proc *p; 220 struct args { 221 int pid; 222 int *status; 223 int options; 224 struct rusage *rusage; 225 int compat; 226 } *uap; 227 int *retval; 228 { 229 230 uap->compat = 0; 231 return (wait1(p, uap, retval)); 232 } 233 #else 234 #define wait1 wait4 235 #endif 236 237 /* 238 * Wait system call. 239 * Search for a terminated (zombie) child, 240 * finally lay it to rest, and collect its status. 241 * Look also for stopped (traced) children, 242 * and pass back status from them. 243 */ 244 wait1(q, uap, retval) 245 register struct proc *q; 246 register struct args { 247 int pid; 248 int *status; 249 int options; 250 struct rusage *rusage; 251 #ifdef COMPAT_43 252 int compat; 253 #endif 254 } *uap; 255 int retval[]; 256 { 257 register int f; 258 register struct proc *p; 259 int status, error; 260 261 if (uap->pid == 0) 262 uap->pid = -q->p_pgid; 263 #ifdef notyet 264 if (uap->options &~ (WUNTRACED|WNOHANG)) 265 return (EINVAL); 266 #endif 267 loop: 268 f = 0; 269 for (p = q->p_cptr; p; p = p->p_osptr) { 270 if (uap->pid != WAIT_ANY && 271 p->p_pid != uap->pid && p->p_pgid != -uap->pid) 272 continue; 273 f++; 274 if (p->p_stat == SZOMB) { 275 retval[0] = p->p_pid; 276 #ifdef COMPAT_43 277 if (uap->compat) 278 retval[1] = p->p_xstat; 279 else 280 #endif 281 if (uap->status) { 282 status = p->p_xstat; /* convert to int */ 283 if (error = copyout((caddr_t)&status, 284 (caddr_t)uap->status, sizeof(status))) 285 return (error); 286 } 287 if (uap->rusage && (error = copyout((caddr_t)p->p_ru, 288 (caddr_t)uap->rusage, sizeof (struct rusage)))) 289 return (error); 290 pgrm(p); /* off pgrp */ 291 p->p_xstat = 0; 292 ruadd(&u.u_cru, p->p_ru); 293 FREE(p->p_ru, M_ZOMBIE); 294 p->p_ru = 0; 295 p->p_stat = NULL; 296 p->p_pid = 0; 297 p->p_ppid = 0; 298 if (*p->p_prev = p->p_nxt) /* off zombproc */ 299 p->p_nxt->p_prev = p->p_prev; 300 p->p_nxt = freeproc; /* onto freeproc */ 301 freeproc = p; 302 if (q = p->p_ysptr) 303 q->p_osptr = p->p_osptr; 304 if (q = p->p_osptr) 305 q->p_ysptr = p->p_ysptr; 306 if ((q = p->p_pptr)->p_cptr == p) 307 q->p_cptr = p->p_osptr; 308 p->p_pptr = 0; 309 p->p_ysptr = 0; 310 p->p_osptr = 0; 311 p->p_cptr = 0; 312 p->p_sig = 0; 313 p->p_sigcatch = 0; 314 p->p_sigignore = 0; 315 p->p_sigmask = 0; 316 /*p->p_pgrp = 0;*/ 317 p->p_flag = 0; 318 p->p_wchan = 0; 319 return (0); 320 } 321 if (p->p_stat == SSTOP && (p->p_flag & SWTED) == 0 && 322 (p->p_flag & STRC || uap->options & WUNTRACED)) { 323 p->p_flag |= SWTED; 324 retval[0] = p->p_pid; 325 #ifdef COMPAT_43 326 if (uap->compat) { 327 retval[1] = W_STOPCODE(p->p_xstat); 328 error = 0; 329 } else 330 #endif 331 if (uap->status) { 332 status = W_STOPCODE(p->p_xstat); 333 error = copyout((caddr_t)&status, 334 (caddr_t)uap->status, sizeof(status)); 335 } else 336 error = 0; 337 return (error); 338 } 339 } 340 if (f == 0) 341 return (ECHILD); 342 if (uap->options & WNOHANG) { 343 retval[0] = 0; 344 return (0); 345 } 346 if (error = tsleep((caddr_t)q, PWAIT | PCATCH, "wait", 0)) 347 return (error); 348 goto loop; 349 } 350