Commit | Line | Data |
---|---|---|
e3d5bfde | 1 | /* kern_exit.c 4.6 83/07/01 */ |
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; | |
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 */ | |
96 | multprog--; | |
97 | p->p_stat = SZOMB; | |
98 | noproc = 1; | |
99 | i = PIDHASH(p->p_pid); | |
100 | x = p - proc; | |
101 | if (pidhash[i] == x) | |
102 | pidhash[i] = p->p_idhash; | |
103 | else { | |
104 | for (i = pidhash[i]; i != 0; i = proc[i].p_idhash) | |
105 | if (proc[i].p_idhash == x) { | |
106 | proc[i].p_idhash = p->p_idhash; | |
107 | goto done; | |
108 | } | |
109 | panic("exit"); | |
110 | } | |
111 | if (p->p_pid == 1) | |
112 | panic("init died"); | |
113 | done: | |
114 | p->p_xstat = rv; | |
115 | if (m == 0) | |
116 | panic("exit: m_getclr"); | |
117 | p->p_ru = mtod(m, struct rusage *); | |
118 | *p->p_ru = u.u_ru; | |
119 | ruadd(p->p_ru, &u.u_cru); | |
120 | for (q = proc; q < procNPROC; q++) | |
121 | if (q->p_pptr == p) { | |
122 | if (q->p_osptr) | |
123 | q->p_osptr->p_ysptr = q->p_ysptr; | |
124 | if (q->p_ysptr) | |
125 | q->p_ysptr->p_osptr = q->p_osptr; | |
126 | if (proc[1].p_cptr) | |
127 | proc[1].p_cptr->p_ysptr = q; | |
128 | q->p_osptr = proc[1].p_cptr; | |
129 | q->p_ysptr = NULL; | |
130 | proc[1].p_cptr = q; | |
131 | ||
132 | q->p_pptr = &proc[1]; | |
133 | q->p_ppid = 1; | |
134 | wakeup((caddr_t)&proc[1]); | |
135 | /* | |
136 | * Traced processes are killed | |
137 | * since their existence means someone is screwing up. | |
138 | * Stopped processes are sent a hangup and a continue. | |
139 | * This is designed to be ``safe'' for setuid | |
140 | * processes since they must be willing to tolerate | |
141 | * hangups anyways. | |
142 | */ | |
143 | if (q->p_flag&STRC) { | |
144 | q->p_flag &= ~STRC; | |
145 | psignal(q, SIGKILL); | |
146 | } else if (q->p_stat == SSTOP) { | |
147 | psignal(q, SIGHUP); | |
148 | psignal(q, SIGCONT); | |
149 | } | |
150 | /* | |
151 | * Protect this process from future | |
152 | * tty signals, clear TSTP/TTIN/TTOU if pending. | |
153 | */ | |
154 | (void) spgrp(q, -1); | |
155 | } | |
156 | psignal(p->p_pptr, SIGCHLD); | |
157 | wakeup((caddr_t)p->p_pptr); | |
158 | swtch(); | |
159 | } | |
160 | ||
161 | wait() | |
162 | { | |
163 | struct rusage ru, *rup; | |
164 | ||
165 | if ((u.u_ar0[PS] & PSL_ALLCC) != PSL_ALLCC) { | |
166 | u.u_error = wait1(0, (struct rusage *)0); | |
167 | return; | |
168 | } | |
169 | rup = (struct rusage *)u.u_ar0[R1]; | |
170 | u.u_error = wait1(u.u_ar0[R0], &ru); | |
171 | if (u.u_error) | |
172 | return; | |
173 | (void) copyout((caddr_t)&ru, (caddr_t)rup, sizeof (struct rusage)); | |
174 | } | |
175 | ||
a8560fa0 SL |
176 | /* |
177 | * Wait system call. | |
178 | * Search for a terminated (zombie) child, | |
179 | * finally lay it to rest, and collect its status. | |
180 | * Look also for stopped (traced) children, | |
181 | * and pass back status from them. | |
182 | */ | |
183 | wait1(options, ru) | |
184 | register int options; | |
185 | struct rusage *ru; | |
186 | { | |
187 | register f; | |
188 | register struct proc *p, *q; | |
189 | ||
190 | f = 0; | |
191 | loop: | |
192 | for (p = proc; p < procNPROC; p++) | |
193 | if (p->p_pptr == u.u_procp) { | |
194 | f++; | |
195 | if (p->p_stat == SZOMB) { | |
196 | u.u_r.r_val1 = p->p_pid; | |
197 | u.u_r.r_val2 = p->p_xstat; | |
198 | p->p_xstat = 0; | |
199 | if (ru) | |
200 | *ru = *p->p_ru; | |
201 | ruadd(&u.u_cru, p->p_ru); | |
202 | (void) m_free(dtom(p->p_ru)); | |
203 | p->p_ru = 0; | |
204 | p->p_stat = NULL; | |
205 | p->p_pid = 0; | |
206 | p->p_ppid = 0; | |
207 | if (q = p->p_ysptr) | |
208 | q->p_osptr = p->p_osptr; | |
209 | if (q = p->p_osptr) | |
210 | q->p_ysptr = p->p_ysptr; | |
211 | if ((q = p->p_pptr)->p_cptr == p) | |
212 | q->p_cptr = p->p_osptr; | |
213 | p->p_pptr = 0; | |
214 | p->p_ysptr = 0; | |
215 | p->p_osptr = 0; | |
216 | p->p_cptr = 0; | |
217 | p->p_sig = 0; | |
dd012d1e SL |
218 | p->p_sigcatch = 0; |
219 | p->p_sigignore = 0; | |
220 | p->p_sigmask = 0; | |
a8560fa0 SL |
221 | p->p_pgrp = 0; |
222 | p->p_flag = 0; | |
223 | p->p_wchan = 0; | |
224 | p->p_cursig = 0; | |
225 | return (0); | |
226 | } | |
227 | if (p->p_stat == SSTOP && (p->p_flag&SWTED)==0 && | |
228 | (p->p_flag&STRC || options&WUNTRACED)) { | |
229 | p->p_flag |= SWTED; | |
230 | u.u_r.r_val1 = p->p_pid; | |
231 | u.u_r.r_val2 = (p->p_cursig<<8) | WSTOPPED; | |
232 | return (0); | |
233 | } | |
234 | } | |
dd012d1e | 235 | if (f == 0) |
a8560fa0 | 236 | return (ECHILD); |
a8560fa0 SL |
237 | if (options&WNOHANG) { |
238 | u.u_r.r_val1 = 0; | |
239 | return (0); | |
240 | } | |
dd012d1e | 241 | if ((u.u_procp->p_flag&SOUSIG) == 0 && setjmp(&u.u_qsave)) { |
a8560fa0 SL |
242 | u.u_eosys = RESTARTSYS; |
243 | return (0); | |
244 | } | |
245 | sleep((caddr_t)u.u_procp, PWAIT); | |
246 | goto loop; | |
247 | } |