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/signalfd.h>
31 #include "sys/event.h"
34 /* Highest signal number supported. POSIX standard signals are < 32 */
38 update_sigmask(const struct filter *filt)
41 rv = signalfd(filt->kf_pfd, &filt->kf_sigmask, 0);
42 dbg_printf("signalfd = %d", filt->kf_pfd);
43 if (rv < 0 || rv != filt->kf_pfd) {
44 dbg_printf("signalfd(2): %s", strerror(errno));
52 evfilt_signal_init(struct filter *filt)
54 sigemptyset(&filt->kf_sigmask);
55 filt->kf_pfd = signalfd(-1, &filt->kf_sigmask, 0);
56 dbg_printf("signalfd = %d", filt->kf_pfd);
64 evfilt_signal_destroy(struct filter *filt)
70 evfilt_signal_copyout(struct filter *filt,
75 struct signalfd_siginfo sig[MAX_KEVENT];
79 n = read(filt->kf_pfd, &sig, nevents * sizeof(sig[0]));
80 if (n < 0 || n < sizeof(sig[0])) {
81 dbg_puts("invalid read from signalfd");
86 for (i = 0, nevents = 0; i < n; i++) {
87 /* This is not an error because of this race condition:
88 * 1. Signal arrives and is queued
89 * 2. The kevent is deleted via kevent(..., EV_DELETE)
90 * 3. The event is dequeued from the signalfd
92 kn = knote_lookup(filt, sig[i].ssi_signo);
96 dbg_printf("got signal %d", sig[i].ssi_signo);
97 memcpy(dst, &kn->kev, sizeof(*dst));
98 /* TODO: dst->data should be the number of times the signal occurred */
101 if (kn->kev.flags & EV_DISPATCH || kn->kev.flags & EV_ONESHOT) {
102 sigdelset(&filt->kf_sigmask, dst->ident);
103 update_sigmask(filt); /* TODO: error checking */
105 if (kn->kev.flags & EV_DISPATCH)
107 if (kn->kev.flags & EV_ONESHOT)
108 knote_free(filt, kn);
118 evfilt_signal_knote_create(struct filter *filt, struct knote *kn)
120 if (kn->kev.ident >= SIGNAL_MAX) {
121 dbg_printf("bad signal number %u", (u_int) kn->kev.ident);
125 kn->kev.flags |= EV_CLEAR;
126 sigaddset(&filt->kf_sigmask, kn->kev.ident);
128 return (update_sigmask(filt));
132 evfilt_signal_knote_modify(struct filter *filt, struct knote *kn,
133 const struct kevent *kev)
135 if (kev.ident >= SIGNAL_MAX) {
136 dbg_printf("bad signal number %u", (u_int) kev.ident);
140 /* Nothing to do since the sigmask does not change. */
146 evfilt_signal_knote_delete(struct filter *filt, struct knote *kn)
148 sigdelset(&filt->kf_sigmask, kn->kev.ident);
150 return (update_sigmask(filt));
154 evfilt_signal_knote_enable(struct filter *filt, struct knote *kn)
156 sigaddset(&filt->kf_sigmask, kn->kev.ident);
158 return (update_sigmask(filt));
162 evfilt_signal_knote_disable(struct filter *filt, struct knote *kn)
164 return (evfilt_signal_knote_delete(filt, kn));
168 const struct filter evfilt_signal = {
171 evfilt_signal_destroy,
172 evfilt_signal_copyout,
173 evfilt_signal_knote_create,
174 evfilt_signal_knote_modify,
175 evfilt_signal_knote_delete,
176 evfilt_signal_knote_enable,
177 evfilt_signal_knote_disable,