signals.c revision 1.4 1 /* $NetBSD: signals.c,v 1.4 2010/11/15 20:37:22 pooka Exp $ */
2
3 /*
4 * Copyright (c) 2010 Antti Kantee. All Rights Reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
16 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 */
27
28 #include <sys/cdefs.h>
29 __KERNEL_RCSID(0, "$NetBSD: signals.c,v 1.4 2010/11/15 20:37:22 pooka Exp $");
30
31 #include <sys/param.h>
32 #include <sys/atomic.h>
33 #include <sys/event.h>
34 #include <sys/proc.h>
35 #include <sys/signal.h>
36
37 #include <rump/rump.h>
38 #include <rump/rumpuser.h>
39
40 #include "rumpkern_if_priv.h"
41
42 const struct filterops sig_filtops;
43 sigset_t sigcantmask;
44
45 /* RUMP_SIGMODEL_PANIC */
46
47 static void
48 rumpsig_panic(pid_t target, int signo)
49 {
50
51 switch (signo) {
52 case SIGSYS:
53 break;
54 default:
55 panic("unhandled signal %d", signo);
56 }
57 }
58
59 /* RUMP_SIGMODEL_IGNORE */
60
61 static void
62 rumpsig_ignore(pid_t target, int signo)
63 {
64
65 return;
66 }
67
68 /* RUMP_SIGMODEL_HOST */
69
70 static void
71 rumpsig_host(pid_t target, int signo)
72 {
73 int error;
74
75 rumpuser_kill(target, signo, &error);
76 }
77
78 /* RUMP_SIGMODEL_RAISE */
79
80 static void
81 rumpsig_raise(pid_t target, int signo)
82 {
83 int error;
84
85 rumpuser_kill(RUMPUSER_PID_SELF, signo, &error);
86 }
87
88 static void
89 rumpsig_record(pid_t target, int sig)
90 {
91 struct proc *p = NULL;
92 struct pgrp *pgrp = NULL;
93
94 /* well this is a little silly */
95 mutex_enter(proc_lock);
96 if (target >= 0)
97 p = proc_find_raw(target);
98 else
99 pgrp = pgrp_find(target);
100
101 if (p) {
102 mutex_enter(p->p_lock);
103 if (!sigismember(&p->p_sigctx.ps_sigignore, sig)) {
104 sigaddset(&p->p_sigpend.sp_set, sig);
105 }
106 mutex_exit(p->p_lock);
107 } else if (pgrp) {
108 LIST_FOREACH(p, &pgrp->pg_members, p_pglist) {
109 mutex_enter(p->p_lock);
110 if (!sigismember(&p->p_sigctx.ps_sigignore, sig)) {
111 sigaddset(&p->p_sigpend.sp_set, sig);
112 }
113 mutex_exit(p->p_lock);
114 }
115 }
116 mutex_exit(proc_lock);
117 }
118
119 typedef void (*rumpsig_fn)(pid_t pid, int sig);
120
121 rumpsig_fn rumpsig = rumpsig_panic;
122
123 /*
124 * Set signal delivery model. It would be nice if we could
125 * take a functional argument. But then we'd need some
126 * OS independent way to represent a signal number and also
127 * a method for easy processing (parsing is boring).
128 *
129 * Plus, upcalls from the rump kernel into process space except
130 * via rumpuser is a somewhat gray area now.
131 */
132 void
133 rump_boot_setsigmodel(enum rump_sigmodel model)
134 {
135
136 switch (model) {
137 case RUMP_SIGMODEL_PANIC:
138 rumpsig = rumpsig_panic;
139 break;
140 case RUMP_SIGMODEL_IGNORE:
141 rumpsig = rumpsig_ignore;
142 break;
143 case RUMP_SIGMODEL_HOST:
144 rumpsig = rumpsig_host;
145 break;
146 case RUMP_SIGMODEL_RAISE:
147 rumpsig = rumpsig_raise;
148 break;
149 case RUMP_SIGMODEL_RECORD:
150 rumpsig = rumpsig_record;
151 break;
152 }
153 }
154
155 void
156 psignal(struct proc *p, int sig)
157 {
158
159 rumpsig(p->p_pid, sig);
160 }
161
162 void
163 pgsignal(struct pgrp *pgrp, int sig, int checktty)
164 {
165
166 rumpsig(-pgrp->pg_id, sig);
167 }
168
169 void
170 kpsignal(struct proc *p, ksiginfo_t *ksi, void *data)
171 {
172
173 rumpsig(p->p_pid, ksi->ksi_signo);
174 }
175
176 void
177 kpgsignal(struct pgrp *pgrp, ksiginfo_t *ksi, void *data, int checkctty)
178 {
179
180 rumpsig(-pgrp->pg_id, ksi->ksi_signo);
181 }
182
183 int
184 sigispending(struct lwp *l, int signo)
185 {
186 struct proc *p = l->l_proc;
187 sigset_t tset;
188
189 tset = p->p_sigpend.sp_set;
190
191 if (signo == 0) {
192 if (firstsig(&tset) != 0)
193 return EINTR;
194 } else if (sigismember(&tset, signo))
195 return EINTR;
196 return 0;
197 }
198
199 void
200 sigpending1(struct lwp *l, sigset_t *ss)
201 {
202 struct proc *p = l->l_proc;
203
204 mutex_enter(p->p_lock);
205 *ss = l->l_proc->p_sigpend.sp_set;
206 mutex_exit(p->p_lock);
207 }
208
209 int
210 sigismasked(struct lwp *l, int sig)
211 {
212
213 return sigismember(&l->l_proc->p_sigctx.ps_sigignore, sig);
214 }
215
216 void
217 sigclear(sigpend_t *sp, const sigset_t *mask, ksiginfoq_t *kq)
218 {
219
220 if (mask == NULL)
221 sigemptyset(&sp->sp_set);
222 else
223 sigminusset(mask, &sp->sp_set);
224 }
225
226 void
227 sigclearall(struct proc *p, const sigset_t *mask, ksiginfoq_t *kq)
228 {
229
230 /* don't assert proc lock, hence callable from user context */
231 sigclear(&p->p_sigpend, mask, kq);
232 }
233
234 void
235 ksiginfo_queue_drain0(ksiginfoq_t *kq)
236 {
237
238 if (!(CIRCLEQ_EMPTY(kq)))
239 panic("how did that get there?");
240 }
241
242 int
243 sigprocmask1(struct lwp *l, int how, const sigset_t *nss, sigset_t *oss)
244 {
245 sigset_t *mask = &l->l_proc->p_sigctx.ps_sigignore;
246
247 KASSERT(mutex_owned(l->l_proc->p_lock));
248
249 if (oss)
250 *oss = *mask;
251
252 if (nss) {
253 switch (how) {
254 case SIG_BLOCK:
255 sigplusset(nss, mask);
256 break;
257 case SIG_UNBLOCK:
258 sigminusset(nss, mask);
259 break;
260 case SIG_SETMASK:
261 *mask = *nss;
262 break;
263 default:
264 return EINVAL;
265 }
266 }
267
268 return 0;
269 }
270
271 void
272 siginit(struct proc *p)
273 {
274
275 sigemptyset(&p->p_sigctx.ps_sigignore);
276 sigemptyset(&p->p_sigpend.sp_set);
277 }
278