signal support for kqueue; support of EV_PERSIST flag to event_set

svn:r18
This commit is contained in:
Niels Provos 2002-04-10 02:10:47 +00:00
parent b855bc5500
commit d10f85dbce
5 changed files with 76 additions and 13 deletions

View File

@ -143,7 +143,8 @@ event_process_active(void)
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);
}
}
@ -324,9 +325,10 @@ event_del(struct event *ev)
}
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);
}
@ -389,7 +391,7 @@ timeout_process(void)
LOG_DBG((LOG_MISC, 60, "timeout_process: call %p",
ev->ev_callback));
event_active(ev, EV_TIMEOUT);
event_active(ev, EV_TIMEOUT, 1);
}
}

11
event.h
View File

@ -47,6 +47,7 @@ extern "C" {
#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
@ -76,6 +77,7 @@ struct event {
int ev_fd;
short ev_events;
short ev_ncalls;
struct timeval ev_timeout;
@ -128,10 +130,17 @@ void timeout_process(void);
#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 *);

View File

@ -33,6 +33,7 @@
#include <sys/time.h>
#include <sys/queue.h>
#include <sys/event.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
@ -215,12 +216,17 @@ kq_dispatch(void *arg, struct timeval *tv)
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);
}
}
@ -234,6 +240,27 @@ kq_add(void *arg, struct event *ev)
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;
@ -272,6 +299,24 @@ kq_del(void *arg, struct event *ev)
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;

View File

@ -41,7 +41,8 @@ main (int argc, char **argv)
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);

View File

@ -56,7 +56,7 @@ extern struct event_list signalqueue;
#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 */
@ -192,8 +192,9 @@ select_dispatch(void *arg, struct timeval *tv)
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;
}
@ -291,10 +292,15 @@ void
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));