Commit | Line | Data |
---|---|---|
bdf8c113 | 1 | /* kern_exit.c 6.5 84/12/20 */ |
a8560fa0 SL |
2 | |
3 | #include "../machine/reg.h" | |
4 | #include "../machine/psl.h" | |
5 | ||
94368568 JB |
6 | #include "param.h" |
7 | #include "systm.h" | |
8 | #include "map.h" | |
9 | #include "dir.h" | |
10 | #include "user.h" | |
11 | #include "kernel.h" | |
12 | #include "proc.h" | |
13 | #include "buf.h" | |
14 | #include "wait.h" | |
15 | #include "vm.h" | |
16 | #include "file.h" | |
17 | #include "mbuf.h" | |
18 | #include "inode.h" | |
a8560fa0 SL |
19 | |
20 | /* | |
21 | * Exit system call: pass back caller's arg | |
22 | */ | |
23 | rexit() | |
24 | { | |
25 | register struct a { | |
26 | int rval; | |
27 | } *uap; | |
28 | ||
29 | uap = (struct a *)u.u_ap; | |
30 | exit((uap->rval & 0377) << 8); | |
31 | } | |
32 | ||
33 | /* | |
34 | * Release resources. | |
35 | * Save u. area for parent to look at. | |
36 | * Enter zombie state. | |
37 | * Wake up parent and init processes, | |
38 | * and dispose of children. | |
39 | */ | |
40 | exit(rv) | |
41 | int rv; | |
42 | { | |
43 | register int i; | |
1d348849 | 44 | register struct proc *p, *q, *nq; |
a8560fa0 SL |
45 | register int x; |
46 | struct mbuf *m = m_getclr(M_WAIT, MT_ZOMBIE); | |
47 | ||
48 | #ifdef PGINPROF | |
49 | vmsizmon(); | |
50 | #endif | |
51 | p = u.u_procp; | |
52 | p->p_flag &= ~(STRC|SULOCK); | |
53 | p->p_flag |= SWEXIT; | |
dd012d1e | 54 | p->p_sigignore = ~0; |
a8560fa0 SL |
55 | p->p_cpticks = 0; |
56 | p->p_pctcpu = 0; | |
dd012d1e | 57 | for (i = 0; i < NSIG; i++) |
a8560fa0 SL |
58 | u.u_signal[i] = SIG_IGN; |
59 | untimeout(realitexpire, (caddr_t)p); | |
60 | /* | |
61 | * Release virtual memory. If we resulted from | |
62 | * a vfork(), instead give the resources back to | |
63 | * the parent. | |
64 | */ | |
65 | if ((p->p_flag & SVFORK) == 0) | |
66 | vrelvm(); | |
67 | else { | |
68 | p->p_flag &= ~SVFORK; | |
69 | wakeup((caddr_t)p); | |
70 | while ((p->p_flag & SVFDONE) == 0) | |
71 | sleep((caddr_t)p, PZERO - 1); | |
72 | p->p_flag &= ~SVFDONE; | |
73 | } | |
74 | for (i = 0; i < NOFILE; i++) { | |
75 | struct file *f; | |
a8560fa0 SL |
76 | |
77 | f = u.u_ofile[i]; | |
78 | u.u_ofile[i] = NULL; | |
a8560fa0 | 79 | u.u_pofile[i] = 0; |
55dfda24 | 80 | closef(f); |
a8560fa0 SL |
81 | } |
82 | ilock(u.u_cdir); | |
83 | iput(u.u_cdir); | |
84 | if (u.u_rdir) { | |
85 | ilock(u.u_rdir); | |
86 | iput(u.u_rdir); | |
87 | } | |
88 | u.u_rlimit[RLIMIT_FSIZE].rlim_cur = RLIM_INFINITY; | |
89 | acct(); | |
90 | #ifdef QUOTA | |
91 | qclean(); | |
a8560fa0 SL |
92 | #endif |
93 | vrelpt(u.u_procp); | |
94 | vrelu(u.u_procp, 0); | |
95 | (void) spl5(); /* hack for mem alloc race XXX */ | |
1d348849 MK |
96 | if (*p->p_prev = p->p_nxt) /* off allproc queue */ |
97 | p->p_nxt->p_prev = p->p_prev; | |
98 | if (p->p_nxt = zombproc) /* onto zombproc */ | |
99 | p->p_nxt->p_prev = &p->p_nxt; | |
100 | p->p_prev = &zombproc; | |
101 | zombproc = p; | |
a8560fa0 SL |
102 | multprog--; |
103 | p->p_stat = SZOMB; | |
104 | noproc = 1; | |
105 | i = PIDHASH(p->p_pid); | |
106 | x = p - proc; | |
107 | if (pidhash[i] == x) | |
108 | pidhash[i] = p->p_idhash; | |
109 | else { | |
110 | for (i = pidhash[i]; i != 0; i = proc[i].p_idhash) | |
111 | if (proc[i].p_idhash == x) { | |
112 | proc[i].p_idhash = p->p_idhash; | |
113 | goto done; | |
114 | } | |
115 | panic("exit"); | |
116 | } | |
117 | if (p->p_pid == 1) | |
118 | panic("init died"); | |
119 | done: | |
120 | p->p_xstat = rv; | |
121 | if (m == 0) | |
122 | panic("exit: m_getclr"); | |
123 | p->p_ru = mtod(m, struct rusage *); | |
124 | *p->p_ru = u.u_ru; | |
125 | ruadd(p->p_ru, &u.u_cru); | |
1d348849 MK |
126 | if (p->p_cptr) /* only need this if any child is S_ZOMB */ |
127 | wakeup((caddr_t)&proc[1]); | |
128 | for (q = p->p_cptr; q != NULL; q = nq) { | |
129 | nq = q->p_osptr; | |
130 | if (nq != NULL) | |
131 | nq->p_ysptr = NULL; | |
132 | if (proc[1].p_cptr) | |
133 | proc[1].p_cptr->p_ysptr = q; | |
134 | q->p_osptr = proc[1].p_cptr; | |
135 | q->p_ysptr = NULL; | |
136 | proc[1].p_cptr = q; | |
a8560fa0 | 137 | |
1d348849 MK |
138 | q->p_pptr = &proc[1]; |
139 | q->p_ppid = 1; | |
140 | /* | |
141 | * Traced processes are killed | |
142 | * since their existence means someone is screwing up. | |
143 | * Stopped processes are sent a hangup and a continue. | |
144 | * This is designed to be ``safe'' for setuid | |
145 | * processes since they must be willing to tolerate | |
146 | * hangups anyways. | |
147 | */ | |
148 | if (q->p_flag&STRC) { | |
149 | q->p_flag &= ~STRC; | |
150 | psignal(q, SIGKILL); | |
151 | } else if (q->p_stat == SSTOP) { | |
152 | psignal(q, SIGHUP); | |
153 | psignal(q, SIGCONT); | |
a8560fa0 | 154 | } |
1d348849 MK |
155 | /* |
156 | * Protect this process from future | |
157 | * tty signals, clear TSTP/TTIN/TTOU if pending. | |
158 | */ | |
159 | (void) spgrp(q, -1); | |
160 | } | |
bdf8c113 | 161 | p->p_cptr = NULL; |
a8560fa0 SL |
162 | psignal(p->p_pptr, SIGCHLD); |
163 | wakeup((caddr_t)p->p_pptr); | |
164 | swtch(); | |
165 | } | |
166 | ||
167 | wait() | |
168 | { | |
169 | struct rusage ru, *rup; | |
170 | ||
171 | if ((u.u_ar0[PS] & PSL_ALLCC) != PSL_ALLCC) { | |
172 | u.u_error = wait1(0, (struct rusage *)0); | |
173 | return; | |
174 | } | |
175 | rup = (struct rusage *)u.u_ar0[R1]; | |
176 | u.u_error = wait1(u.u_ar0[R0], &ru); | |
177 | if (u.u_error) | |
178 | return; | |
326bf897 SL |
179 | if (rup != (struct rusage *)0) |
180 | u.u_error = copyout((caddr_t)&ru, (caddr_t)rup, | |
181 | sizeof (struct rusage)); | |
a8560fa0 SL |
182 | } |
183 | ||
a8560fa0 SL |
184 | /* |
185 | * Wait system call. | |
186 | * Search for a terminated (zombie) child, | |
187 | * finally lay it to rest, and collect its status. | |
188 | * Look also for stopped (traced) children, | |
189 | * and pass back status from them. | |
190 | */ | |
191 | wait1(options, ru) | |
192 | register int options; | |
193 | struct rusage *ru; | |
194 | { | |
195 | register f; | |
196 | register struct proc *p, *q; | |
197 | ||
198 | f = 0; | |
199 | loop: | |
1d348849 MK |
200 | q = u.u_procp; |
201 | for (p = q->p_cptr; p; p = p->p_osptr) { | |
a8560fa0 SL |
202 | f++; |
203 | if (p->p_stat == SZOMB) { | |
204 | u.u_r.r_val1 = p->p_pid; | |
205 | u.u_r.r_val2 = p->p_xstat; | |
206 | p->p_xstat = 0; | |
207 | if (ru) | |
208 | *ru = *p->p_ru; | |
209 | ruadd(&u.u_cru, p->p_ru); | |
210 | (void) m_free(dtom(p->p_ru)); | |
211 | p->p_ru = 0; | |
212 | p->p_stat = NULL; | |
213 | p->p_pid = 0; | |
214 | p->p_ppid = 0; | |
1d348849 MK |
215 | if (*p->p_prev = p->p_nxt) /* off zombproc */ |
216 | p->p_nxt->p_prev = p->p_prev; | |
217 | p->p_nxt = freeproc; /* onto freeproc */ | |
218 | freeproc = p; | |
a8560fa0 SL |
219 | if (q = p->p_ysptr) |
220 | q->p_osptr = p->p_osptr; | |
221 | if (q = p->p_osptr) | |
222 | q->p_ysptr = p->p_ysptr; | |
223 | if ((q = p->p_pptr)->p_cptr == p) | |
224 | q->p_cptr = p->p_osptr; | |
225 | p->p_pptr = 0; | |
226 | p->p_ysptr = 0; | |
227 | p->p_osptr = 0; | |
228 | p->p_cptr = 0; | |
229 | p->p_sig = 0; | |
dd012d1e SL |
230 | p->p_sigcatch = 0; |
231 | p->p_sigignore = 0; | |
232 | p->p_sigmask = 0; | |
a8560fa0 SL |
233 | p->p_pgrp = 0; |
234 | p->p_flag = 0; | |
235 | p->p_wchan = 0; | |
236 | p->p_cursig = 0; | |
237 | return (0); | |
238 | } | |
239 | if (p->p_stat == SSTOP && (p->p_flag&SWTED)==0 && | |
240 | (p->p_flag&STRC || options&WUNTRACED)) { | |
241 | p->p_flag |= SWTED; | |
242 | u.u_r.r_val1 = p->p_pid; | |
243 | u.u_r.r_val2 = (p->p_cursig<<8) | WSTOPPED; | |
244 | return (0); | |
245 | } | |
246 | } | |
dd012d1e | 247 | if (f == 0) |
a8560fa0 | 248 | return (ECHILD); |
a8560fa0 SL |
249 | if (options&WNOHANG) { |
250 | u.u_r.r_val1 = 0; | |
251 | return (0); | |
252 | } | |
dd012d1e | 253 | if ((u.u_procp->p_flag&SOUSIG) == 0 && setjmp(&u.u_qsave)) { |
a8560fa0 SL |
254 | u.u_eosys = RESTARTSYS; |
255 | return (0); | |
256 | } | |
257 | sleep((caddr_t)u.u_procp, PWAIT); | |
258 | goto loop; | |
259 | } |