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