2 * Copyright (c) 2009 Mark Heily <mark@heily.com>
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23 #include <sys/queue.h>
24 #include <sys/socket.h>
25 #include <sys/types.h>
29 #include "sys/event.h"
32 /* Highest signal number supported. POSIX standard signals are < 32 */
36 struct filter *s_filt;
37 struct knote *s_knote;
38 volatile uint32_t s_cnt;
41 static pthread_mutex_t sigtbl_mtx = PTHREAD_MUTEX_INITIALIZER;
42 static struct sentry sigtbl[SIGNAL_MAX];
45 signal_handler(int sig)
47 struct sentry *s = &sigtbl[sig];
49 dbg_printf("caught sig=%d", sig);
50 atomic_inc(&s->s_cnt);
52 if (port_send(s->s_filt->kf_kqueue->kq_port,
53 X_PORT_SOURCE_SIGNAL, &sigtbl[sig]) < 0) {
54 return; //FIXME: errorhandling
57 (void)write(s->s_filt->kf_wfd, &sig, sizeof(sig));//FIXME:errhandling
62 catch_signal(struct filter *filt, struct knote *kn)
68 memset(&sa, 0, sizeof(sa));
69 sa.sa_handler = signal_handler;
70 sa.sa_flags |= SA_RESTART;
71 sigfillset(&sa.sa_mask);
73 if (sigaction(kn->kev.ident, &sa, NULL) == -1) {
74 dbg_perror("sigaction");
77 /* FIXME: will clobber previous entry, if any */
78 pthread_mutex_lock(&sigtbl_mtx);
79 sigtbl[kn->kev.ident].s_filt = filt;
80 sigtbl[kn->kev.ident].s_knote = kn;
81 pthread_mutex_unlock(&sigtbl_mtx);
83 dbg_printf("installed handler for signal %d", sig);
88 ignore_signal(int sig)
92 memset(&sa, 0, sizeof(sa));
93 sa.sa_handler = SIG_IGN;
94 sigemptyset(&sa.sa_mask);
96 if (sigaction(sig, &sa, NULL) == -1) {
97 dbg_perror("sigaction");
100 pthread_mutex_lock(&sigtbl_mtx);
101 sigtbl[sig].s_filt = NULL;
102 sigtbl[sig].s_knote = NULL;
103 pthread_mutex_unlock(&sigtbl_mtx);
105 dbg_printf("removed handler for signal %d", sig);
110 evfilt_signal_init(struct filter *filt)
112 return filter_socketpair(filt);
116 evfilt_signal_destroy(struct filter *filt)
122 evfilt_signal_knote_create(struct filter *filt, struct knote *kn)
124 if (kn->kev.ident >= SIGNAL_MAX) {
125 dbg_printf("unsupported signal number %u",
126 (unsigned int) kn->kev.ident);
130 kn->kev.flags |= EV_CLEAR;
132 return catch_signal(filt, kn);
136 evfilt_signal_knote_modify(struct filter *filt, struct knote *kn,
137 const struct kevent *kev)
139 kn->kev.flags = kev->flags | EV_CLEAR;
144 evfilt_signal_knote_delete(struct filter *filt, struct knote *kn)
146 return ignore_signal(kn->kev.ident);
150 evfilt_signal_knote_enable(struct filter *filt, struct knote *kn)
152 return catch_signal(filt, kn);
156 evfilt_signal_knote_disable(struct filter *filt, struct knote *kn)
158 return ignore_signal(kn->kev.ident);
162 evfilt_signal_copyout(struct filter *filt,
171 port_event_t *pe = (port_event_t *) pthread_getspecific(filt->kf_kqueue->kq_port_event);
173 s = (struct sentry *) pe->portev_user;
174 sig = s - &sigtbl[0];
176 read(filt->kf_pfd, &sig, sizeof(sig));//FIXME:errhandling
181 //TODO: READ counter: s->s_knote->kev.data = ?;
182 /* TODO: dst->data should be the number of times the signal occurred */
184 dst->filter = EVFILT_SIGNAL;
185 dst->udata = kn->kev.udata;
186 dst->flags = kn->kev.flags;
190 if (kn->kev.flags & EV_DISPATCH) {
191 ignore_signal(kn->kev.ident);
193 } else if (kn->kev.flags & EV_ONESHOT) {
194 ignore_signal(kn->kev.ident);
195 knote_free(filt, kn);
201 const struct filter evfilt_signal = {
204 evfilt_signal_destroy,
205 evfilt_signal_copyout,
206 evfilt_signal_knote_create,
207 evfilt_signal_knote_modify,
208 evfilt_signal_knote_delete,
209 evfilt_signal_knote_enable,
210 evfilt_signal_knote_disable,