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