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.
24 #include <sys/queue.h>
25 #include <sys/types.h>
31 #include <sys/inotify.h>
32 #include <sys/epoll.h>
34 #include "sys/event.h"
38 /* XXX-FIXME Should only have one wait_thread per process.
39 Now, there is one thread per kqueue
43 pthread_cond_t wait_cond;
44 pthread_mutex_t wait_mtx;
47 //FIXME: WANT: static void *
49 wait_thread(void *arg)
51 struct filter *filt = (struct filter *) arg;
53 const int options = WEXITED | WNOWAIT;
58 /* Block all signals */
59 sigfillset (&sigmask);
60 pthread_sigmask(SIG_BLOCK, &sigmask, NULL);
64 /* Wait for a child process to exit(2) */
65 if (waitid(P_ALL, 0, &si, options) != 0) {
66 if (errno == ECHILD) {
67 dbg_puts("got ECHILD, waiting for wakeup condition");
68 pthread_mutex_lock(&filt->kf_data->wait_mtx);
69 pthread_cond_wait(&filt->kf_data->wait_cond, &filt->kf_data->wait_mtx);
70 pthread_mutex_unlock(&filt->kf_data->wait_mtx);
71 dbg_puts("awoken from ECHILD-induced sleep");
75 dbg_puts(" waitid(2) returned");
78 dbg_perror("waitid(2)");
82 /* Scan the wait queue to see if anyone is interested */
83 kn = knote_lookup(filt, si.si_pid);
87 /* Create a proc_event */
88 if (si.si_code == CLD_EXITED) {
89 kn->kev.data = si.si_status;
90 } else if (si.si_code == CLD_KILLED) {
91 /* FIXME: probably not true on BSD */
92 /* FIXME: arbitrary non-zero number */
95 /* Should never happen. */
96 /* FIXME: arbitrary non-zero number */
100 knote_enqueue(filt, kn);
102 /* Indicate read(2) readiness */
103 if (write(filt->kf_pfd, &counter, sizeof(counter)) < 0) {
104 if (errno != EAGAIN) {
105 dbg_printf("write(2): %s", strerror(errno));
106 /* TODO: set filter error flag */
112 /* TODO: error handling */
118 evfilt_proc_init(struct filter *filt)
121 struct evfilt_data *ed;
124 if ((ed = calloc(1, sizeof(*ed))) == NULL)
128 pthread_mutex_init(&ed->wait_mtx, NULL);
129 pthread_cond_init(&ed->wait_cond, NULL);
130 if ((efd = eventfd(0, 0)) < 0)
132 if (fcntl(filt->kf_pfd, F_SETFL, O_NONBLOCK) < 0)
135 if (pthread_create(&ed->wthr_id, NULL, wait_thread, filt) != 0)
148 return (-1); /*STUB*/
152 evfilt_proc_destroy(struct filter *filt)
154 //TODO: pthread_cancel(filt->kf_data->wthr_id);
159 evfilt_proc_copyout(struct filter *filt,
167 /* Reset the counter */
168 if (read(filt->kf_pfd, &cur, sizeof(cur)) < sizeof(cur)) {
169 dbg_printf("read(2): %s", strerror(errno));
172 dbg_printf(" counter=%llu", (unsigned long long) cur);
174 for (kn = knote_dequeue(filt); kn != NULL; kn = knote_dequeue(filt)) {
175 kevent_dump(&kn->kev);
176 memcpy(dst, &kn->kev, sizeof(*dst));
178 if (kn->kev.flags & EV_DISPATCH) {
181 if (kn->kev.flags & EV_ONESHOT) {
182 knote_free(filt, kn);
184 kn->kev.data = 0; //why??
188 if (++nevents > maxevents)
193 if (knote_events_pending(filt)) {
194 /* XXX-FIXME: If there are leftover events on the waitq,
195 re-arm the eventfd. list */
203 evfilt_proc_knote_create(struct filter *filt, struct knote *kn)
205 return (0); /* STUB */
209 evfilt_proc_knote_modify(struct filter *filt, struct knote *kn,
210 const struct kevent *kev)
212 return (0); /* STUB */
216 evfilt_proc_knote_delete(struct filter *filt, struct knote *kn)
218 return (0); /* STUB */
222 evfilt_proc_knote_enable(struct filter *filt, struct knote *kn)
224 return (0); /* STUB */
228 evfilt_proc_knote_disable(struct filter *filt, struct knote *kn)
230 return (0); /* STUB */
233 const struct filter evfilt_proc_DEADWOOD = {
234 0, //XXX-FIXME broken: EVFILT_PROC,
238 evfilt_proc_knote_create,
239 evfilt_proc_knote_modify,
240 evfilt_proc_knote_delete,
241 evfilt_proc_knote_enable,
242 evfilt_proc_knote_disable,