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.27 (Berkeley) 08/29/90 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 "vm.h" 21 #include "file.h" 22 #include "vnode.h" 23 #include "syslog.h" 24 #include "malloc.h" 25 26 #include "machine/reg.h" 27 #ifdef COMPAT_43 28 #include "machine/psl.h" 29 #endif 30 31 /* 32 * Exit system call: pass back caller's arg 33 */ 34 /* ARGSUSED */ 35 rexit(p, uap, retval) 36 struct proc *p; 37 struct args { 38 int rval; 39 } *uap; 40 int *retval; 41 { 42 43 exit(p, W_EXITCODE(uap->rval, 0)); 44 /* NOTREACHED */ 45 } 46 47 /* 48 * Release resources. 49 * Save u. area for parent to look at. 50 * Enter zombie state. 51 * Wake up parent and init processes, 52 * and dispose of children. 53 */ 54 exit(p, rv) 55 struct proc *p; 56 int rv; 57 { 58 register int i; 59 register struct proc *q, *nq; 60 register struct proc **pp; 61 62 #ifdef PGINPROF 63 vmsizmon(); 64 #endif 65 MALLOC(p->p_ru, struct rusage *, sizeof(struct rusage), 66 M_ZOMBIE, M_WAITOK); 67 p->p_flag &= ~(STRC|SULOCK); 68 p->p_flag |= SWEXIT; 69 p->p_sigignore = ~0; 70 p->p_sig = 0; 71 p->p_cpticks = 0; 72 p->p_pctcpu = 0; 73 for (i = 0; i < NSIG; i++) 74 u.u_signal[i] = SIG_IGN; 75 untimeout(realitexpire, (caddr_t)p); 76 /* 77 * Release virtual memory. If we resulted from 78 * a vfork(), instead give the resources back to 79 * the parent. 80 */ 81 if ((p->p_flag & SVFORK) == 0) { 82 #ifdef MAPMEM 83 if (u.u_mmap) 84 (void) mmexit(p); 85 #endif 86 vrelvm(); 87 } else { 88 p->p_flag &= ~SVFORK; 89 wakeup((caddr_t)p); 90 while ((p->p_flag & SVFDONE) == 0) 91 sleep((caddr_t)p, PZERO - 1); 92 p->p_flag &= ~SVFDONE; 93 } 94 for (i = 0; i <= u.u_lastfile; i++) { 95 struct file *f; 96 97 f = u.u_ofile[i]; 98 if (f) { 99 u.u_ofile[i] = NULL; 100 u.u_pofile[i] = 0; 101 (void) closef(f); 102 } 103 } 104 if (SESS_LEADER(p)) { 105 register struct session *sp = p->p_session; 106 107 if (sp->s_ttyvp) { 108 /* 109 * Controlling process. 110 * Signal foreground pgrp and revoke access 111 * to controlling terminal. 112 */ 113 if (sp->s_ttyp->t_pgrp) 114 pgsignal(sp->s_ttyp->t_pgrp, SIGHUP, 1); 115 vgoneall(sp->s_ttyvp); 116 vrele(sp->s_ttyvp); 117 sp->s_ttyvp = NULL; 118 /* 119 * s_ttyp is not zero'd; we use this to indicate 120 * that the session once had a controlling terminal. 121 * (for logging and informational purposes) 122 */ 123 } 124 sp->s_leader = 0; 125 } 126 VOP_LOCK(u.u_cdir); 127 vput(u.u_cdir); 128 if (u.u_rdir) { 129 VOP_LOCK(u.u_rdir); 130 vput(u.u_rdir); 131 } 132 u.u_rlimit[RLIMIT_FSIZE].rlim_cur = RLIM_INFINITY; 133 (void) acct(p); 134 crfree(u.u_cred); 135 #ifdef KTRACE 136 /* 137 * release trace file 138 */ 139 if (p->p_tracep) 140 vrele(p->p_tracep); 141 #endif 142 /* 143 * Freeing the user structure and kernel stack 144 * for the current process: have to run a bit longer 145 * using the pages which are about to be freed... 146 * vrelu will block memory allocation by raising ipl. 147 */ 148 vrelu(p, 0); 149 vrelpt(p); 150 if (*p->p_prev = p->p_nxt) /* off allproc queue */ 151 p->p_nxt->p_prev = p->p_prev; 152 if (p->p_nxt = zombproc) /* onto zombproc */ 153 p->p_nxt->p_prev = &p->p_nxt; 154 p->p_prev = &zombproc; 155 zombproc = p; 156 multprog--; 157 p->p_stat = SZOMB; 158 noproc = 1; 159 for (pp = &pidhash[PIDHASH(p->p_pid)]; *pp; pp = &(*pp)->p_hash) 160 if (*pp == p) { 161 *pp = p->p_hash; 162 goto done; 163 } 164 panic("exit"); 165 done: 166 if (p->p_pid == 1) { 167 if (p->p_dsize == 0) { 168 printf("Can't exec init (errno %d)\n", WEXITSTATUS(rv)); 169 for (;;) 170 ; 171 } else 172 panic("init died"); 173 } 174 p->p_xstat = rv; 175 *p->p_ru = u.u_ru; 176 i = splclock(); 177 p->p_ru->ru_stime = p->p_stime; 178 p->p_ru->ru_utime = p->p_utime; 179 splx(i); 180 ruadd(p->p_ru, &u.u_cru); 181 if (p->p_cptr) /* only need this if any child is S_ZOMB */ 182 wakeup((caddr_t)&proc[1]); 183 fixjobc(p, 0); 184 for (q = p->p_cptr; q != NULL; q = nq) { 185 nq = q->p_osptr; 186 if (nq != NULL) 187 nq->p_ysptr = NULL; 188 if (proc[1].p_cptr) 189 proc[1].p_cptr->p_ysptr = q; 190 q->p_osptr = proc[1].p_cptr; 191 q->p_ysptr = NULL; 192 proc[1].p_cptr = q; 193 194 q->p_pptr = &proc[1]; 195 q->p_ppid = 1; 196 /* 197 * Traced processes are killed 198 * since their existence means someone is screwing up. 199 */ 200 if (q->p_flag&STRC) { 201 q->p_flag &= ~STRC; 202 psignal(q, SIGKILL); 203 } 204 } 205 p->p_cptr = NULL; 206 psignal(p->p_pptr, SIGCHLD); 207 wakeup((caddr_t)p->p_pptr); 208 #if defined(tahoe) 209 dkeyrelease(p->p_dkey), p->p_dkey = 0; 210 ckeyrelease(p->p_ckey), p->p_ckey = 0; 211 u.u_pcb.pcb_savacc.faddr = (float *)NULL; 212 #endif 213 swtch(); 214 } 215 216 #ifdef COMPAT_43 217 owait(p, uap, retval) 218 struct proc *p; 219 register struct args { 220 int pid; 221 int *status; 222 int options; 223 struct rusage *rusage; 224 int compat; 225 } *uap; 226 int *retval; 227 { 228 229 if ((u.u_ar0[PS] & PSL_ALLCC) != PSL_ALLCC) { 230 uap->options = 0; 231 uap->rusage = 0; 232 } else { 233 uap->options = u.u_ar0[R0]; 234 uap->rusage = (struct rusage *)u.u_ar0[R1]; 235 } 236 uap->pid = WAIT_ANY; 237 uap->status = 0; 238 uap->compat = 1; 239 return (wait1(p, uap, retval)); 240 } 241 242 wait4(p, uap, retval) 243 struct proc *p; 244 struct args { 245 int pid; 246 int *status; 247 int options; 248 struct rusage *rusage; 249 int compat; 250 } *uap; 251 int *retval; 252 { 253 254 uap->compat = 0; 255 return (wait1(p, uap, retval)); 256 } 257 #else 258 #define wait1 wait4 259 #endif 260 261 /* 262 * Wait system call. 263 * Search for a terminated (zombie) child, 264 * finally lay it to rest, and collect its status. 265 * Look also for stopped (traced) children, 266 * and pass back status from them. 267 */ 268 wait1(q, uap, retval) 269 register struct proc *q; 270 register struct args { 271 int pid; 272 int *status; 273 int options; 274 struct rusage *rusage; 275 #ifdef COMPAT_43 276 int compat; 277 #endif 278 } *uap; 279 int retval[]; 280 { 281 register int f; 282 register struct proc *p; 283 int status, error; 284 285 if (uap->pid == 0) 286 uap->pid = -q->p_pgid; 287 #ifdef notyet 288 if (uap->options &~ (WUNTRACED|WNOHANG)) 289 return (EINVAL); 290 #endif 291 loop: 292 f = 0; 293 for (p = q->p_cptr; p; p = p->p_osptr) { 294 if (uap->pid != WAIT_ANY && 295 p->p_pid != uap->pid && p->p_pgid != -uap->pid) 296 continue; 297 f++; 298 if (p->p_stat == SZOMB) { 299 retval[0] = p->p_pid; 300 #ifdef COMPAT_43 301 if (uap->compat) 302 retval[1] = p->p_xstat; 303 else 304 #endif 305 if (uap->status) { 306 status = p->p_xstat; /* convert to int */ 307 if (error = copyout((caddr_t)&status, 308 (caddr_t)uap->status, sizeof(status))) 309 return (error); 310 } 311 if (uap->rusage && (error = copyout((caddr_t)p->p_ru, 312 (caddr_t)uap->rusage, sizeof (struct rusage)))) 313 return (error); 314 pgrm(p); /* off pgrp */ 315 p->p_xstat = 0; 316 ruadd(&u.u_cru, p->p_ru); 317 FREE(p->p_ru, M_ZOMBIE); 318 p->p_ru = 0; 319 p->p_stat = NULL; 320 p->p_pid = 0; 321 p->p_ppid = 0; 322 if (*p->p_prev = p->p_nxt) /* off zombproc */ 323 p->p_nxt->p_prev = p->p_prev; 324 p->p_nxt = freeproc; /* onto freeproc */ 325 freeproc = p; 326 if (q = p->p_ysptr) 327 q->p_osptr = p->p_osptr; 328 if (q = p->p_osptr) 329 q->p_ysptr = p->p_ysptr; 330 if ((q = p->p_pptr)->p_cptr == p) 331 q->p_cptr = p->p_osptr; 332 p->p_pptr = 0; 333 p->p_ysptr = 0; 334 p->p_osptr = 0; 335 p->p_cptr = 0; 336 p->p_sig = 0; 337 p->p_sigcatch = 0; 338 p->p_sigignore = 0; 339 p->p_sigmask = 0; 340 /*p->p_pgrp = 0;*/ 341 p->p_flag = 0; 342 p->p_wchan = 0; 343 return (0); 344 } 345 if (p->p_stat == SSTOP && (p->p_flag & SWTED) == 0 && 346 (p->p_flag & STRC || uap->options & WUNTRACED)) { 347 p->p_flag |= SWTED; 348 retval[0] = p->p_pid; 349 #ifdef COMPAT_43 350 if (uap->compat) { 351 retval[1] = W_STOPCODE(p->p_xstat); 352 error = 0; 353 } else 354 #endif 355 if (uap->status) { 356 status = W_STOPCODE(p->p_xstat); 357 error = copyout((caddr_t)&status, 358 (caddr_t)uap->status, sizeof(status)); 359 } else 360 error = 0; 361 return (error); 362 } 363 } 364 if (f == 0) 365 return (ECHILD); 366 if (uap->options & WNOHANG) { 367 retval[0] = 0; 368 return (0); 369 } 370 if (error = tsleep((caddr_t)q, PWAIT | PCATCH, "wait", 0)) 371 return (error); 372 goto loop; 373 } 374