All user events take a void *data
[akaros.git] / user / parlib / signal.c
1 /* Copyright (c) 2013 The Regents of the University of California
2  * Barret Rhoden <brho@cs.berkeley.edu>
3  * Kevin Klues <klueska@cs.berkeley.edu>
4  * See LICENSE for details.
5  *
6  * POSIX signal handling glue.  All glibc programs link against parlib, so they
7  * will get this mixed in.  Mostly just registration of signal handlers.
8  *
9  * POSIX signal handling caveats:
10  *      - We don't copy signal handling tables or anything across forks or execs
11  *      - We don't send meaningful info in the siginfos, nor do we pass pid/uids on
12  *      signals coming from a kill.  This is especially pertinent for sigqueue,
13  *      which needs a payload (value) and sending PID
14  *      - We run handlers in vcore context, so any blocking syscall will spin.
15  *      Regular signals have restrictions on their syscalls too, though not this
16  *      great.  We could spawn off a uthread to run the handler, given that we have
17  *      a 2LS (which we don't for SCPs).
18  *      - We don't do anything with signal blocking/masking.  When in a signal
19  *      handler, you won't get interrupted with another signal handler (so long as
20  *      you run it in vcore context!).  With uthreads, you could get interrupted.
21  *      There is also no process wide signal blocking yet (sigprocmask()).  If this
22  *      is desired, we can abort certain signals when we h_p_signal(), 
23  *      - Likewise, we don't do waiting for particular signals yet.  Just about the
24  *      only thing we do is allow the registration of signal handlers. 
25  *      - Check each function for further notes.  */
26
27 #include <signal.h>
28 #include <stdio.h>
29
30 #include <event.h>
31 #include <errno.h>
32 #include <assert.h>
33 #include <ros/procinfo.h>
34 #include <ros/syscall.h>
35
36 /* This is list of sigactions associated with each posix signal. */
37 static struct sigaction sigactions[_NSIG - 1];
38
39 /* These are the default handlers for each posix signal.  They are listed in
40  * SIGNAL(7) of the Linux Programmer's Manual */
41 /* Exit codes are set as suggested in the following link.  I wish I could find
42  * the definitive source, but this will have to do for now.
43  * http://unix.stackexchange.com/questions/99112/default-exit-code-when-process-is-terminated
44  * */
45 static void default_term_handler(int signr)
46 {
47         ros_syscall(SYS_proc_destroy, __procinfo.pid, signr, 0, 0, 0, 0);
48 }
49 static void default_core_handler(int signr)
50 {
51         fprintf(stderr, "Segmentation Fault (sorry, no core dump yet)\n");
52         default_term_handler((1 << 7) + signr);
53 }
54 static void default_stop_handler(int signr)
55 {
56         fprintf(stderr, "Stop signal received!  No support to stop yet though!\n");
57 }
58 static void default_cont_handler(int signr)
59 {
60         fprintf(stderr, "Cont signal received!  No support to cont yet though!\n");
61 }
62 static __sighandler_t default_handlers[] = {
63         [SIGHUP]    = default_term_handler, 
64         [SIGINT]    = default_term_handler, 
65         [SIGQUIT]   = default_core_handler, 
66         [SIGILL]    = default_core_handler, 
67         [SIGTRAP]   = default_core_handler, 
68         [SIGABRT]   = default_core_handler, 
69         [SIGIOT]    = default_core_handler, 
70         [SIGBUS]    = default_core_handler, 
71         [SIGFPE]    = default_core_handler, 
72         [SIGKILL]   = default_term_handler, 
73         [SIGUSR1]   = default_term_handler, 
74         [SIGSEGV]   = default_core_handler, 
75         [SIGUSR2]   = default_term_handler, 
76         [SIGPIPE]   = default_term_handler, 
77         [SIGALRM]   = default_term_handler, 
78         [SIGTERM]   = default_term_handler, 
79         [SIGSTKFLT] = default_term_handler, 
80         [SIGCHLD]   = SIG_IGN, 
81         [SIGCONT]   = default_cont_handler, 
82         [SIGSTOP]   = default_stop_handler, 
83         [SIGTSTP]   = default_stop_handler, 
84         [SIGTTIN]   = default_stop_handler, 
85         [SIGTTOU]   = default_stop_handler, 
86         [SIGURG]    = default_term_handler, 
87         [SIGXCPU]   = SIG_IGN, 
88         [SIGXFSZ]   = default_core_handler, 
89         [SIGVTALRM] = default_term_handler, 
90         [SIGPROF]   = default_term_handler, 
91         [SIGWINCH]  = SIG_IGN, 
92         [SIGIO]     = default_term_handler, 
93         [SIGPWR]    = SIG_IGN, 
94         [SIGSYS]    = default_core_handler
95 };
96
97
98 /* This is the akaros posix signal trigger.  Signals are dispatched from
99  * this function to their proper posix signal handler */
100 void trigger_posix_signal(int sig_nr, struct siginfo *info, void *aux)
101 {
102         struct sigaction *action;
103         if (sig_nr > _NSIG - 1 || sig_nr < 0)
104                 return;
105         action = &sigactions[sig_nr];
106         /* Would like a switch/case here, but they are pointers.  We can also get
107          * away with this check early since sa_handler and sa_sigaction are macros
108          * referencing the same union.  The man page isn't specific about whether or
109          * not you need to care about SA_SIGINFO when sending DFL/ERR/IGN. */
110         if (action->sa_handler == SIG_ERR)
111                 return;
112         if (action->sa_handler == SIG_IGN)
113                 return;
114         if (action->sa_handler == SIG_DFL) {
115                 if (default_handlers[sig_nr] != SIG_IGN)
116                         default_handlers[sig_nr](sig_nr);
117                 return;
118         }
119
120         if (action->sa_flags & SA_SIGINFO) {
121                 /* If NULL info struct passed in, construct our own */
122                 struct siginfo s = {0};
123                 if (info == NULL)
124                         info = &s;
125                 /* Make sure the caller either already set singo in the info struct, or
126                  * if they didn't, make sure it has been zeroed out (i.e. not just some
127                  * garbage on the stack. */
128                 assert(info->si_signo == sig_nr || info->si_signo == 0);
129                 info->si_signo = sig_nr;
130                 /* TODO: consider info->pid and whatnot */
131                 /* We assume that this function follows the proper calling convention
132                  * (i.e. it wasn't written in some crazy assembly function that
133                  * trashes all its registers, i.e GO's default runtime handler) */
134                 action->sa_sigaction(sig_nr, info, aux);
135         } else {
136                 action->sa_handler(sig_nr);
137         }
138 }
139
140 /* This is the catch all akaros event->posix signal handler.  All posix signals
141  * are received in a single akaros event type.  They are then dispatched from
142  * this function to their proper posix signal handler */
143 static void handle_event(struct event_msg *ev_msg, unsigned int ev_type,
144                          void *data)
145 {
146         int sig_nr;
147         struct siginfo info = {0};
148         info.si_code = SI_USER;
149
150         assert(ev_msg);
151         sig_nr = ev_msg->ev_arg1;
152         trigger_posix_signal(sig_nr, &info, 0);
153 }
154
155 /* Called from uthread_slim_init() */
156 void init_posix_signals(void)
157 {
158         struct event_queue *posix_sig_ev_q;
159         ev_handlers[EV_POSIX_SIGNAL] = handle_event;
160         posix_sig_ev_q = get_big_event_q();
161         assert(posix_sig_ev_q);
162         posix_sig_ev_q->ev_flags = EVENT_IPI | EVENT_INDIR | EVENT_FALLBACK;
163         register_kevent_q(posix_sig_ev_q, EV_POSIX_SIGNAL);
164 }
165
166 int sigaddset(sigset_t *__set, int __signo)
167 {
168         if (__signo == 0 || __signo > _NSIG) {
169                 errno = EINVAL;
170                 return -1;
171         }
172         __sigaddset(__set, __signo);
173         return 0;
174 }
175
176 int sigdelset(sigset_t *__set, int __signo)
177 {
178         if (__signo == 0 || __signo > _NSIG) {
179                 errno = EINVAL;
180                 return -1;
181         }
182         __sigdelset(__set, __signo);
183         return 0;
184 }
185
186 int sigismember(__const sigset_t *__set, int __signo)
187 {
188         if (__signo == 0 || __signo > _NSIG) {
189                 errno = EINVAL;
190                 return -1;
191         }
192         __sigismember(__set, __signo);
193         return 0;
194 }
195
196 /* Would need a layer/interposition to ignore blocked signals when they come in,
197  * and then to manually play them when they are unblocked, like how x86 does
198  * with the IRR and the ISR for interrupt delivery. */
199 int sigprocmask(int __how, __const sigset_t *__restrict __set,
200                 sigset_t *__restrict __oset)
201 {
202         printf("Function not supported generically! "
203            "Use 2LS specific function e.g. pthread_sigmask\n");
204         return 0;
205 }
206
207 /* Could do this with a loop on delivery of the signal, sleeping and getting
208  * woken up by the kernel on any event, like we do with async syscalls. */
209 int sigsuspend(__const sigset_t *__set)
210 {
211         return 0;
212 }
213
214 int sigaction(int __sig, __const struct sigaction *__restrict __act,
215               struct sigaction *__restrict __oact)
216 {
217         if (__sig > _NSIG - 1 || __sig < 0)
218                 return -1;
219         if (__oact) {
220                 *__oact = sigactions[__sig];
221         }
222         if (!__act)
223                 return 0;
224         sigactions[__sig] = *__act;
225         return 0;
226 }
227
228 /* Not really possible or relevant - you'd need to walk/examine the event UCQ */
229 int sigpending(sigset_t *__set)
230 {
231         return 0;
232 }
233
234 /* Can be done similar to sigsuspend */
235 int sigwait(__const sigset_t *__restrict __set, int *__restrict __sig)
236 {
237         return 0;
238 }
239
240 /* Can be done similar to sigsuspend */
241 int sigwaitinfo(__const sigset_t *__restrict __set,
242                 siginfo_t *__restrict __info)
243 {
244         return 0;
245 }
246
247 /* Can be done similar to sigsuspend, with an extra alarm syscall */
248 int sigtimedwait(__const sigset_t *__restrict __set,
249                  siginfo_t *__restrict __info,
250                  __const struct timespec *__restrict __timeout)
251 {
252         return 0;
253 }
254
255 /* Needs support with trigger_posix_signal to deal with passing values with POSIX
256  * signals. */
257 int sigqueue(__pid_t __pid, int __sig, __const union sigval __val)
258 {
259         return 0;
260 }
261
262 /* Old BSD interface, deprecated */
263 int sigvec(int __sig, __const struct sigvec *__vec, struct sigvec *__ovec)
264 {
265         return 0;
266 }
267
268 /* Linux specific, and not really needed for us */
269 int sigreturn(struct sigcontext *__scp)
270 {
271         return 0;
272 }
273
274 /* Akaros can't have signals interrupt syscalls to need a restart, though we can
275  * re-wake-up the process while it is waiting for its syscall. */
276 int siginterrupt(int __sig, int __interrupt)
277 {
278         return 0;
279 }
280
281 /* This is managed by vcore / 2LS code */
282 int sigstack(struct sigstack *__ss, struct sigstack *__oss)
283 {
284         return 0;
285 }
286
287 /* This is managed by vcore / 2LS code */
288 int sigaltstack(__const struct sigaltstack *__restrict __ss,
289                 struct sigaltstack *__restrict __oss)
290 {
291         return 0;
292 }