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