df3c7b8873af3190baed26ccb2e24b8319a2982e
[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  * See LICENSE for details.
4  *
5  * POSIX signal handling glue.  All glibc programs link against parlib, so they
6  * will get this mixed in.  Mostly just registration of signal handlers.
7  *
8  * POSIX signal handling caveats:
9  *      - We don't copy signal handling tables or anything across forks or execs
10  *      - We don't send meaningful info in the siginfos, nor do we pass pid/uids on
11  *      signals coming from a kill.  This is especially pertinent for sigqueue,
12  *      which needs a payload (value) and sending PID
13  *      - We run handlers in vcore context, so any blocking syscall will spin.
14  *      Regular signals have restrictions on their syscalls too, though not this
15  *      great.  We could spawn off a uthread to run the handler, given that we have
16  *      a 2LS (which we don't for SCPs).
17  *      - We don't do anything with signal blocking/masking.  When in a signal
18  *      handler, you won't get interrupted with another signal handler (so long as
19  *      you run it in vcore context!).  With uthreads, you could get interrupted.
20  *      There is also no process wide signal blocking yet (sigprocmask()).  If this
21  *      is desired, we can abort certain signals when we h_p_signal(), 
22  *      - Likewise, we don't do waiting for particular signals yet.  Just about the
23  *      only thing we do is allow the registration of signal handlers. 
24  *      - Check each function for further notes.  */
25
26 #include <signal.h>
27 #include <stdio.h>
28
29 #include <event.h>
30 #include <assert.h>
31
32 struct sigaction sigactions[_NSIG - 1];
33
34 void handle_posix_signal(struct event_msg *ev_msg, unsigned int ev_type)
35 {
36         int sig_nr;
37         struct sigaction *action;
38         struct siginfo info = {0};
39         assert(ev_msg);
40         sig_nr = ev_msg->ev_arg1;
41         if (sig_nr > _NSIG - 1 || sig_nr < 0)
42                 return;
43         action = &sigactions[sig_nr];
44         /* Would like a switch/case here, but they are pointers.  We can also get
45          * away with this check early since sa_handler and sa_sigaction are macros
46          * referencing the same union.  The man page isn't specific about whether or
47          * not you need to care about SA_SIGINFO when sending DFL/ERR/IGN. */
48         if (action->sa_handler == SIG_ERR)
49                 return;
50         if (action->sa_handler == SIG_IGN)
51                 return;
52         if (action->sa_handler == SIG_DFL)      /* aka, 0 */
53                 return;
54         if (action->sa_flags & SA_SIGINFO) {
55                 info.si_signo = sig_nr;
56                 /* TODO: consider pid and whatnot */
57                 action->sa_sigaction(sig_nr, &info, 0);
58         } else {
59                 action->sa_handler(sig_nr);
60         }
61 }
62
63 /* Called from uthread_slim_init() */
64 void init_posix_signals(void)
65 {
66         struct event_queue *posix_sig_ev_q;
67         ev_handlers[EV_POSIX_SIGNAL] = handle_posix_signal;
68         posix_sig_ev_q = get_big_event_q();
69         assert(posix_sig_ev_q);
70         posix_sig_ev_q->ev_flags = EVENT_IPI | EVENT_INDIR | EVENT_FALLBACK;
71         register_kevent_q(posix_sig_ev_q, EV_POSIX_SIGNAL);
72 }
73
74 /* Will need to do these if we have signal masks (sigprocmask style) */
75 int sigaddset(sigset_t *__set, int __signo)
76 {
77         return 0;
78 }
79
80 int sigdelset(sigset_t *__set, int __signo)
81 {
82         return 0;
83 }
84
85 int sigismember(__const sigset_t *__set, int __signo)
86 {
87         return 0;
88 }
89
90 /* Would need a layer/interposition to ignore blocked signals when they come in,
91  * and then to manually play them when they are unblocked, like how x86 does
92  * with the IRR and the ISR for interrupt delivery. */
93 int sigprocmask(int __how, __const sigset_t *__restrict __set,
94                 sigset_t *__restrict __oset)
95 {
96         return 0;
97 }
98
99 /* Could do this with a loop on delivery of the signal, sleeping and getting
100  * woken up by the kernel on any event, like we do with async syscalls. */
101 int sigsuspend(__const sigset_t *__set)
102 {
103         return 0;
104 }
105
106 int sigaction(int __sig, __const struct sigaction *__restrict __act,
107               struct sigaction *__restrict __oact)
108 {
109         if (__sig > _NSIG - 1 || __sig < 0)
110                 return -1;
111         if (__oact) {
112                 *__oact = sigactions[__sig];
113         }
114         if (!__act)
115                 return 0;
116         sigactions[__sig] = *__act;
117         return 0;
118 }
119
120 /* Not really possible or relevant - you'd need to walk/examine the event UCQ */
121 int sigpending(sigset_t *__set)
122 {
123         return 0;
124 }
125
126 /* Can be done similar to sigsuspend */
127 int sigwait(__const sigset_t *__restrict __set, int *__restrict __sig)
128 {
129         return 0;
130 }
131
132 /* Can be done similar to sigsuspend */
133 int sigwaitinfo(__const sigset_t *__restrict __set,
134                 siginfo_t *__restrict __info)
135 {
136         return 0;
137 }
138
139 /* Can be done similar to sigsuspend, with an extra alarm syscall */
140 int sigtimedwait(__const sigset_t *__restrict __set,
141                  siginfo_t *__restrict __info,
142                  __const struct timespec *__restrict __timeout)
143 {
144         return 0;
145 }
146
147 /* Needs support with handle_posix_signal to deal with passing values with POSIX
148  * signals. */
149 int sigqueue(__pid_t __pid, int __sig, __const union sigval __val)
150 {
151         return 0;
152 }
153
154 /* Old BSD interface, deprecated */
155 int sigvec(int __sig, __const struct sigvec *__vec, struct sigvec *__ovec)
156 {
157         return 0;
158 }
159
160 /* Linux specific, and not really needed for us */
161 int sigreturn(struct sigcontext *__scp)
162 {
163         return 0;
164 }
165
166 /* Akaros can't have signals interrupt syscalls to need a restart, though we can
167  * re-wake-up the process while it is waiting for its syscall. */
168 int siginterrupt(int __sig, int __interrupt)
169 {
170         return 0;
171 }
172
173 /* This is managed by vcore / 2LS code */
174 int sigstack(struct sigstack *__ss, struct sigstack *__oss)
175 {
176         return 0;
177 }
178
179 /* This is managed by vcore / 2LS code */
180 int sigaltstack(__const struct sigaltstack *__restrict __ss,
181                 struct sigaltstack *__restrict __oss)
182 {
183         return 0;
184 }