ev = TAILQ_FIRST(&activequeue)) {
event_queue_remove(ev, EVLIST_ACTIVE);
- (*ev->ev_callback)(ev->ev_fd, ev->ev_res, ev->ev_arg);
+ while (ev->ev_ncalls--)
+ (*ev->ev_callback)(ev->ev_fd, ev->ev_res, ev->ev_arg);
}
}
}
void
-event_active(struct event *ev, int res)
+event_active(struct event *ev, int res, short ncalls)
{
ev->ev_res = res;
+ ev->ev_ncalls = ncalls;
event_queue_insert(ev, EVLIST_ACTIVE);
}
LOG_DBG((LOG_MISC, 60, "timeout_process: call %p",
ev->ev_callback));
- event_active(ev, EV_TIMEOUT);
+ event_active(ev, EV_TIMEOUT, 1);
}
}
#define EV_READ 0x02
#define EV_WRITE 0x04
#define EV_SIGNAL 0x08
+#define EV_PERSIST 0x10 /* Persistant event */
/* Fix so that ppl dont have to run with <sys/queue.h> */
#ifndef TAILQ_ENTRY
int ev_fd;
short ev_events;
+ short ev_ncalls;
struct timeval ev_timeout;
#define timeout_pending(ev, tv) event_pending(ev, EV_TIMEOUT, tv)
#define timeout_initialized(ev) ((ev)->ev_flags & EVLIST_INIT)
+#define signal_add(ev, tv) event_add(ev, tv)
+#define signal_set(ev, x, cb, arg) \
+ event_set(ev, x, EV_SIGNAL|EV_PERSIST, cb, arg)
+#define signal_del(ev) event_del(ev)
+#define signal_pending(ev, tv) event_pending(ev, EV_SIGNAL, tv)
+#define signal_initialized(ev) ((ev)->ev_flags & EVLIST_INIT)
+
void event_set(struct event *, int, short, void (*)(int, short, void *), void *);
int event_add(struct event *, struct timeval *);
int event_del(struct event *);
- void event_active(struct event *, int);
+void event_active(struct event *, int, short);
int event_pending(struct event *, short, struct timeval *);
#include <sys/time.h>
#include <sys/queue.h>
#include <sys/event.h>
+#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
which |= EV_READ;
} else if (events[i].filter == EVFILT_WRITE) {
which |= EV_WRITE;
+ } else if (events[i].filter == EVFILT_SIGNAL) {
+ which |= EV_SIGNAL;
}
if (which) {
- ev->ev_flags &= ~EVLIST_X_KQINKERNEL;
- event_del(ev);
- event_active(ev, which);
+ if (!(ev->ev_events & EV_PERSIST)) {
+ ev->ev_flags &= ~EVLIST_X_KQINKERNEL;
+ event_del(ev);
+ }
+ event_active(ev, which,
+ ev->ev_events & EV_SIGNAL ? events[i].data : 1);
}
}
struct kqop *kqop = arg;
struct kevent kev;
+ if (ev->ev_events & EV_SIGNAL) {
+ int nsignal = EVENT_SIGNAL(ev);
+
+ memset(&kev, 0, sizeof(kev));
+ kev.ident = nsignal;
+ kev.filter = EVFILT_SIGNAL;
+ kev.flags = EV_ADD;
+ if (!(ev->ev_events & EV_PERSIST))
+ kev.filter |= EV_ONESHOT;
+ kev.udata = ev;
+
+ if (kq_insert(kqop, &kev) == -1)
+ return (-1);
+
+ if (signal(nsignal, SIG_IGN) == SIG_ERR)
+ return (-1);
+
+ ev->ev_flags |= EVLIST_X_KQINKERNEL;
+ return (0);
+ }
+
if (ev->ev_events & EV_READ) {
memset(&kev, 0, sizeof(kev));
kev.ident = ev->ev_fd;
if (!(ev->ev_flags & EVLIST_X_KQINKERNEL))
return (0);
+ if (ev->ev_events & EV_SIGNAL) {
+ int nsignal = EVENT_SIGNAL(ev);
+
+ memset(&kev, 0, sizeof(kev));
+ kev.ident = signal;
+ kev.filter = EVFILT_SIGNAL;
+ kev.flags = EV_DELETE;
+
+ if (kq_insert(kqop, &kev) == -1)
+ return (-1);
+
+ if (signal(nsignal, SIG_DFL) == SIG_ERR)
+ return (-1);
+
+ ev->ev_flags &= ~EVLIST_X_KQINKERNEL;
+ return (0);
+ }
+
if (ev->ev_events & EV_READ) {
memset(&kev, 0, sizeof(kev));
kev.ident = ev->ev_fd;
event_init();
/* Initalize one event */
- event_set(&signal_int, SIGINT, EV_SIGNAL, signal_cb, &signal_int);
+ event_set(&signal_int, SIGINT, EV_SIGNAL|EV_PERSIST, signal_cb,
+ &signal_int);
event_add(&signal_int, NULL);
#define howmany(x, y) (((x)+((y)-1))/(y))
#endif
-int evsigcaught[NSIG];
+short evsigcaught[NSIG];
struct selectop {
int event_fds; /* Highest fd in fd set */
res &= ev->ev_events;
if (res) {
- event_del(ev);
- event_active(ev, res);
+ if (!(ev->ev_events & EV_PERSIST))
+ event_del(ev);
+ event_active(ev, res, 1);
} else if (ev->ev_fd > maxfd)
maxfd = ev->ev_fd;
}
signal_process(void)
{
struct event *ev;
+ short ncalls;
TAILQ_FOREACH(ev, &signalqueue, ev_signal_next) {
- if (evsigcaught[EVENT_SIGNAL(ev)])
- event_active(ev, EV_SIGNAL);
+ ncalls = evsigcaught[EVENT_SIGNAL(ev)];
+ if (ncalls) {
+ if (!(ev->ev_events & EV_PERSIST))
+ event_del(ev);
+ event_active(ev, EV_SIGNAL, ncalls);
+ }
}
memset(evsigcaught, 0, sizeof(evsigcaught));