1 /* 2 * Copyright (c) 1982, 1986, 1988 Regents of the University of California. 3 * All rights reserved. The Berkeley software License Agreement 4 * specifies the terms and conditions for redistribution. 5 * 6 * @(#)kern_exit.c 7.6 (Berkeley) 04/25/89 7 */ 8 9 #include "param.h" 10 #include "systm.h" 11 #include "map.h" 12 #include "dir.h" 13 #include "user.h" 14 #include "kernel.h" 15 #include "proc.h" 16 #include "buf.h" 17 #include "wait.h" 18 #include "vm.h" 19 #include "file.h" 20 #include "inode.h" 21 #include "tty.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 /* 31 * Exit system call: pass back caller's arg 32 */ 33 rexit() 34 { 35 register struct a { 36 int rval; 37 } *uap; 38 union wait status; 39 40 uap = (struct a *)u.u_ap; 41 status.w_status = 0; 42 status.w_retcode = uap->rval; 43 exit(status.w_status); 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(rv) 54 int rv; /* should be union wait (XXX) */ 55 { 56 register int i; 57 register struct proc *p, *q, *nq; 58 register int x; 59 60 #ifdef PGINPROF 61 vmsizmon(); 62 #endif 63 p = u.u_procp; 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_cpticks = 0; 70 p->p_pctcpu = 0; 71 for (i = 0; i < NSIG; i++) 72 u.u_signal[i] = SIG_IGN; 73 untimeout(realitexpire, (caddr_t)p); 74 /* 75 * Release virtual memory. If we resulted from 76 * a vfork(), instead give the resources back to 77 * the parent. 78 */ 79 if ((p->p_flag & SVFORK) == 0) 80 vrelvm(); 81 else { 82 p->p_flag &= ~SVFORK; 83 wakeup((caddr_t)p); 84 while ((p->p_flag & SVFDONE) == 0) 85 sleep((caddr_t)p, PZERO - 1); 86 p->p_flag &= ~SVFDONE; 87 } 88 for (i = 0; i <= u.u_lastfile; i++) { 89 struct file *f; 90 91 f = u.u_ofile[i]; 92 if (f) { 93 u.u_ofile[i] = NULL; 94 u.u_pofile[i] = 0; 95 closef(f); 96 } 97 } 98 if (SESS_LEADER(p)) { 99 p->p_session->s_leader = 0; 100 /* TODO: vhangup(); */ 101 if (u.u_ttyp) { 102 u.u_ttyp->t_session = 0; 103 u.u_ttyp->t_pgid = 0; 104 } 105 } 106 ilock(u.u_cdir); 107 iput(u.u_cdir); 108 if (u.u_rdir) { 109 ilock(u.u_rdir); 110 iput(u.u_rdir); 111 } 112 u.u_rlimit[RLIMIT_FSIZE].rlim_cur = RLIM_INFINITY; 113 acct(); 114 #ifdef QUOTA 115 qclean(); 116 #endif 117 #ifdef KTRACE 118 /* 119 * release trace file 120 */ 121 if (p->p_tracep) 122 irele(p->p_tracep); 123 #endif 124 /* 125 /* 126 * Freeing the user structure and kernel stack 127 * for the current process: have to run a bit longer 128 * using the pages which are about to be freed... 129 * vrelu will block memory allocation by raising ipl. 130 */ 131 vrelu(u.u_procp, 0); 132 vrelpt(u.u_procp); 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 multprog--; 140 p->p_stat = SZOMB; 141 noproc = 1; 142 i = PIDHASH(p->p_pid); 143 x = p - proc; 144 if (pidhash[i] == x) 145 pidhash[i] = p->p_idhash; 146 else { 147 for (i = pidhash[i]; i != 0; i = proc[i].p_idhash) 148 if (proc[i].p_idhash == x) { 149 proc[i].p_idhash = p->p_idhash; 150 goto done; 151 } 152 panic("exit"); 153 } 154 if (p->p_pid == 1) { 155 if (p->p_dsize == 0) { 156 printf("Can't exec init (errno %d)\n", rv >> 8); 157 for (;;) 158 ; 159 } else 160 panic("init died"); 161 } 162 done: 163 p->p_xstat = rv; 164 *p->p_ru = u.u_ru; 165 ruadd(p->p_ru, &u.u_cru); 166 if (p->p_cptr) /* only need this if any child is S_ZOMB */ 167 wakeup((caddr_t)&proc[1]); 168 if (PGRP_JOBC(p)) 169 p->p_pgrp->pg_jobc--; 170 for (q = p->p_cptr; q != NULL; q = nq) { 171 if (PGRP_JOBC(q)) 172 q->p_pgrp->pg_jobc--; 173 nq = q->p_osptr; 174 if (nq != NULL) 175 nq->p_ysptr = NULL; 176 if (proc[1].p_cptr) 177 proc[1].p_cptr->p_ysptr = q; 178 q->p_osptr = proc[1].p_cptr; 179 q->p_ysptr = NULL; 180 proc[1].p_cptr = q; 181 182 q->p_pptr = &proc[1]; 183 q->p_ppid = 1; 184 /* 185 * Traced processes are killed 186 * since their existence means someone is screwing up. 187 * Stopped processes are sent a hangup and a continue. 188 * This is designed to be ``safe'' for setuid 189 * processes since they must be willing to tolerate 190 * hangups anyways. 191 */ 192 if (q->p_flag&STRC) { 193 q->p_flag &= ~STRC; 194 psignal(q, SIGKILL); 195 } else if (q->p_stat == SSTOP) { 196 psignal(q, SIGHUP); 197 psignal(q, SIGCONT); 198 } 199 /* 200 * Protect this process from future 201 * tty signals, clear TSTP/TTIN/TTOU if pending. 202 */ 203 (void) spgrp(q); 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() 218 { 219 struct a { 220 int pid; 221 union wait *status; 222 int options; 223 struct rusage *rusage; 224 } *uap = (struct a *)u.u_ap; 225 226 if ((u.u_ar0[PS] & PSL_ALLCC) != PSL_ALLCC) { 227 uap->options = WSIGRESTART; 228 uap->rusage = 0; 229 } else { 230 uap->options = u.u_ar0[R0] | WSIGRESTART; 231 uap->rusage = (struct rusage *)u.u_ar0[R1]; 232 } 233 uap->pid = WAIT_ANY; 234 uap->status = 0; 235 wait1(1); 236 } 237 238 wait4() 239 { 240 wait1(0); 241 } 242 #endif 243 244 /* 245 * Wait system call. 246 * Search for a terminated (zombie) child, 247 * finally lay it to rest, and collect its status. 248 * Look also for stopped (traced) children, 249 * and pass back status from them. 250 */ 251 #ifdef COMPAT_43 252 wait1(compat) 253 int compat; 254 #else 255 wait4() 256 #endif 257 { 258 register struct a { 259 int pid; 260 union wait *status; 261 int options; 262 struct rusage *rusage; 263 } *uap = (struct a *)u.u_ap; 264 register f; 265 register struct proc *p, *q; 266 union wait status; 267 268 f = 0; 269 q = u.u_procp; 270 if (uap->pid == 0) 271 uap->pid = -q->p_pgid; 272 if (uap->options &~ (WUNTRACED|WNOHANG|WSIGRESTART)) { 273 u.u_error = EINVAL; 274 return; 275 } 276 loop: 277 for (p = q->p_cptr; p; p = p->p_osptr) { 278 if (uap->pid != WAIT_ANY && 279 p->p_pid != uap->pid && p->p_pgid != -uap->pid) 280 continue; 281 f++; 282 if (p->p_stat == SZOMB) { 283 pgrm(p); /* off pgrp */ 284 u.u_r.r_val1 = p->p_pid; 285 #ifdef COMPAT_43 286 if (compat) 287 u.u_r.r_val2 = p->p_xstat; 288 else 289 #endif 290 if (uap->status) { 291 status.w_status = p->p_xstat; 292 if (u.u_error = copyout((caddr_t)&status, 293 (caddr_t)uap->status, sizeof(status))) 294 return; 295 } 296 p->p_xstat = 0; 297 if (uap->rusage) 298 u.u_error = copyout((caddr_t)p->p_ru, 299 (caddr_t)uap->rusage, 300 sizeof (struct rusage)); 301 ruadd(&u.u_cru, p->p_ru); 302 FREE(p->p_ru, M_ZOMBIE); 303 p->p_ru = 0; 304 p->p_stat = NULL; 305 p->p_pid = 0; 306 p->p_ppid = 0; 307 if (*p->p_prev = p->p_nxt) /* off zombproc */ 308 p->p_nxt->p_prev = p->p_prev; 309 p->p_nxt = freeproc; /* onto freeproc */ 310 freeproc = p; 311 if (q = p->p_ysptr) 312 q->p_osptr = p->p_osptr; 313 if (q = p->p_osptr) 314 q->p_ysptr = p->p_ysptr; 315 if ((q = p->p_pptr)->p_cptr == p) 316 q->p_cptr = p->p_osptr; 317 p->p_pptr = 0; 318 p->p_ysptr = 0; 319 p->p_osptr = 0; 320 p->p_cptr = 0; 321 p->p_sig = 0; 322 p->p_sigcatch = 0; 323 p->p_sigignore = 0; 324 p->p_sigmask = 0; 325 /*p->p_pgrp = 0;*/ 326 p->p_flag = 0; 327 p->p_wchan = 0; 328 p->p_cursig = 0; 329 return; 330 } 331 if (p->p_stat == SSTOP && (p->p_flag & SWTED) == 0 && 332 (p->p_flag & STRC || uap->options & WUNTRACED)) { 333 p->p_flag |= SWTED; 334 u.u_r.r_val1 = p->p_pid; 335 #ifdef COMPAT_43 336 if (compat) 337 u.u_r.r_val2 = (p->p_cursig<<8) | WSTOPPED; 338 else 339 #endif 340 if (uap->status) { 341 status.w_status = 0; 342 status.w_stopval = WSTOPPED; 343 status.w_stopsig = p->p_cursig; 344 u.u_error = copyout((caddr_t)&status, 345 (caddr_t)uap->status, sizeof(status)); 346 } 347 return; 348 } 349 } 350 if (f == 0) { 351 u.u_error = ECHILD; 352 return; 353 } 354 if (uap->options & WNOHANG) { 355 u.u_r.r_val1 = 0; 356 return; 357 } 358 if (uap->options & WSIGRESTART && setjmp(&u.u_qsave)) { 359 p = u.u_procp; 360 if ((u.u_sigintr & sigmask(p->p_cursig)) != 0) { 361 u.u_error = EINTR; 362 return; 363 } 364 u.u_eosys = RESTARTSYS; 365 return; 366 } 367 sleep((caddr_t)u.u_procp, PWAIT); 368 goto loop; 369 } 370