new signals
[unix-history] / usr / src / sys / kern / kern_exit.c
CommitLineData
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 */
23rexit()
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 */
40exit(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");
118done:
119 p->p_xstat = rv;
120if (m == 0)
121panic("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
166wait()
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 */
188wait1(options, ru)
189 register int options;
190 struct rusage *ru;
191{
192 register f;
193 register struct proc *p, *q;
194
195 f = 0;
196loop:
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}