Commit | Line | Data |
---|---|---|
dd012d1e | 1 | /* kern_exit.c 4.3 83/06/02 */ |
a8560fa0 SL |
2 | |
3 | #include "../machine/reg.h" | |
4 | #include "../machine/psl.h" | |
5 | ||
6 | #include "../h/param.h" | |
7 | #include "../h/systm.h" | |
8 | #include "../h/map.h" | |
9 | #include "../h/dir.h" | |
10 | #include "../h/user.h" | |
11 | #include "../h/kernel.h" | |
12 | #include "../h/proc.h" | |
13 | #include "../h/buf.h" | |
14 | #include "../h/wait.h" | |
15 | #include "../h/vm.h" | |
16 | #include "../h/file.h" | |
17 | #include "../h/mbuf.h" | |
18 | #include "../h/inode.h" | |
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; | |
44 | register struct proc *p, *q; | |
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; | |
76 | int po; | |
77 | ||
78 | f = u.u_ofile[i]; | |
79 | u.u_ofile[i] = NULL; | |
80 | po = u.u_pofile[i]; | |
81 | u.u_pofile[i] = 0; | |
82 | closef(f, po); | |
83 | } | |
84 | ilock(u.u_cdir); | |
85 | iput(u.u_cdir); | |
86 | if (u.u_rdir) { | |
87 | ilock(u.u_rdir); | |
88 | iput(u.u_rdir); | |
89 | } | |
90 | u.u_rlimit[RLIMIT_FSIZE].rlim_cur = RLIM_INFINITY; | |
91 | acct(); | |
92 | #ifdef QUOTA | |
93 | qclean(); | |
94 | #endif | |
95 | #ifdef sun | |
96 | ctxfree(u.u_procp); | |
97 | #endif | |
98 | vrelpt(u.u_procp); | |
99 | vrelu(u.u_procp, 0); | |
100 | (void) spl5(); /* hack for mem alloc race XXX */ | |
101 | multprog--; | |
102 | p->p_stat = SZOMB; | |
103 | noproc = 1; | |
104 | i = PIDHASH(p->p_pid); | |
105 | x = p - proc; | |
106 | if (pidhash[i] == x) | |
107 | pidhash[i] = p->p_idhash; | |
108 | else { | |
109 | for (i = pidhash[i]; i != 0; i = proc[i].p_idhash) | |
110 | if (proc[i].p_idhash == x) { | |
111 | proc[i].p_idhash = p->p_idhash; | |
112 | goto done; | |
113 | } | |
114 | panic("exit"); | |
115 | } | |
116 | if (p->p_pid == 1) | |
117 | panic("init died"); | |
118 | done: | |
119 | p->p_xstat = rv; | |
120 | if (m == 0) | |
121 | panic("exit: m_getclr"); | |
122 | p->p_ru = mtod(m, struct rusage *); | |
123 | *p->p_ru = u.u_ru; | |
124 | ruadd(p->p_ru, &u.u_cru); | |
125 | for (q = proc; q < procNPROC; q++) | |
126 | if (q->p_pptr == p) { | |
127 | if (q->p_osptr) | |
128 | q->p_osptr->p_ysptr = q->p_ysptr; | |
129 | if (q->p_ysptr) | |
130 | q->p_ysptr->p_osptr = q->p_osptr; | |
131 | if (proc[1].p_cptr) | |
132 | proc[1].p_cptr->p_ysptr = q; | |
133 | q->p_osptr = proc[1].p_cptr; | |
134 | q->p_ysptr = NULL; | |
135 | proc[1].p_cptr = q; | |
136 | ||
137 | q->p_pptr = &proc[1]; | |
138 | q->p_ppid = 1; | |
139 | wakeup((caddr_t)&proc[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); | |
154 | } | |
155 | /* | |
156 | * Protect this process from future | |
157 | * tty signals, clear TSTP/TTIN/TTOU if pending. | |
158 | */ | |
159 | (void) spgrp(q, -1); | |
160 | } | |
161 | psignal(p->p_pptr, SIGCHLD); | |
162 | wakeup((caddr_t)p->p_pptr); | |
163 | swtch(); | |
164 | } | |
165 | ||
166 | wait() | |
167 | { | |
168 | struct rusage ru, *rup; | |
169 | ||
170 | if ((u.u_ar0[PS] & PSL_ALLCC) != PSL_ALLCC) { | |
171 | u.u_error = wait1(0, (struct rusage *)0); | |
172 | return; | |
173 | } | |
174 | rup = (struct rusage *)u.u_ar0[R1]; | |
175 | u.u_error = wait1(u.u_ar0[R0], &ru); | |
176 | if (u.u_error) | |
177 | return; | |
178 | (void) copyout((caddr_t)&ru, (caddr_t)rup, sizeof (struct rusage)); | |
179 | } | |
180 | ||
a8560fa0 SL |
181 | /* |
182 | * Wait system call. | |
183 | * Search for a terminated (zombie) child, | |
184 | * finally lay it to rest, and collect its status. | |
185 | * Look also for stopped (traced) children, | |
186 | * and pass back status from them. | |
187 | */ | |
188 | wait1(options, ru) | |
189 | register int options; | |
190 | struct rusage *ru; | |
191 | { | |
192 | register f; | |
193 | register struct proc *p, *q; | |
194 | ||
195 | f = 0; | |
196 | loop: | |
197 | for (p = proc; p < procNPROC; p++) | |
198 | if (p->p_pptr == u.u_procp) { | |
199 | f++; | |
200 | if (p->p_stat == SZOMB) { | |
201 | u.u_r.r_val1 = p->p_pid; | |
202 | u.u_r.r_val2 = p->p_xstat; | |
203 | p->p_xstat = 0; | |
204 | if (ru) | |
205 | *ru = *p->p_ru; | |
206 | ruadd(&u.u_cru, p->p_ru); | |
207 | (void) m_free(dtom(p->p_ru)); | |
208 | p->p_ru = 0; | |
209 | p->p_stat = NULL; | |
210 | p->p_pid = 0; | |
211 | p->p_ppid = 0; | |
212 | if (q = p->p_ysptr) | |
213 | q->p_osptr = p->p_osptr; | |
214 | if (q = p->p_osptr) | |
215 | q->p_ysptr = p->p_ysptr; | |
216 | if ((q = p->p_pptr)->p_cptr == p) | |
217 | q->p_cptr = p->p_osptr; | |
218 | p->p_pptr = 0; | |
219 | p->p_ysptr = 0; | |
220 | p->p_osptr = 0; | |
221 | p->p_cptr = 0; | |
222 | p->p_sig = 0; | |
dd012d1e SL |
223 | p->p_sigcatch = 0; |
224 | p->p_sigignore = 0; | |
225 | p->p_sigmask = 0; | |
a8560fa0 SL |
226 | p->p_pgrp = 0; |
227 | p->p_flag = 0; | |
228 | p->p_wchan = 0; | |
229 | p->p_cursig = 0; | |
230 | return (0); | |
231 | } | |
232 | if (p->p_stat == SSTOP && (p->p_flag&SWTED)==0 && | |
233 | (p->p_flag&STRC || options&WUNTRACED)) { | |
234 | p->p_flag |= SWTED; | |
235 | u.u_r.r_val1 = p->p_pid; | |
236 | u.u_r.r_val2 = (p->p_cursig<<8) | WSTOPPED; | |
237 | return (0); | |
238 | } | |
239 | } | |
dd012d1e | 240 | if (f == 0) |
a8560fa0 | 241 | return (ECHILD); |
a8560fa0 SL |
242 | if (options&WNOHANG) { |
243 | u.u_r.r_val1 = 0; | |
244 | return (0); | |
245 | } | |
dd012d1e | 246 | if ((u.u_procp->p_flag&SOUSIG) == 0 && setjmp(&u.u_qsave)) { |
a8560fa0 SL |
247 | u.u_eosys = RESTARTSYS; |
248 | return (0); | |
249 | } | |
250 | sleep((caddr_t)u.u_procp, PWAIT); | |
251 | goto loop; | |
252 | } |