Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

libevent 0.5

  • Loading branch information...
commit c26ec4ce115b8479c3a13a2917cc15782ef60ef0 1 parent 384663c
itojun authored
View
58 kame/kame/faithd.libevent/event.c
@@ -81,6 +81,7 @@ void event_queue_remove(struct event *, int);
static RB_HEAD(event_tree, event) timetree;
static struct event_list activequeue;
+struct event_list signalqueue;
struct event_list eventqueue;
static struct timeval event_tv;
@@ -111,6 +112,7 @@ event_init(void)
RB_INIT(&timetree);
TAILQ_INIT(&eventqueue);
TAILQ_INIT(&activequeue);
+ TAILQ_INIT(&signalqueue);
evbase = NULL;
for (i = 0; eventops[i] && !evbase; i++) {
@@ -129,19 +131,27 @@ int
event_haveevents(void)
{
return (RB_ROOT(&timetree) || TAILQ_FIRST(&eventqueue) ||
- TAILQ_FIRST(&activequeue));
+ TAILQ_FIRST(&signalqueue) || TAILQ_FIRST(&activequeue));
}
void
event_process_active(void)
{
struct event *ev;
+ short ncalls;
for (ev = TAILQ_FIRST(&activequeue); ev;
ev = TAILQ_FIRST(&activequeue)) {
event_queue_remove(ev, EVLIST_ACTIVE);
- (*ev->ev_callback)(ev->ev_fd, ev->ev_res, ev->ev_arg);
+ /* Allows deletes to work */
+ ncalls = ev->ev_ncalls;
+ ev->ev_pncalls = &ncalls;
+ while (ncalls) {
+ ncalls--;
+ ev->ev_ncalls = ncalls;
+ (*ev->ev_callback)(ev->ev_fd, ev->ev_res, ev->ev_arg);
+ }
}
}
@@ -226,6 +236,8 @@ event_set(struct event *ev, int fd, short events,
ev->ev_fd = fd;
ev->ev_events = events;
ev->ev_flags = EVLIST_INIT;
+ ev->ev_ncalls = 0;
+ ev->ev_pncalls = NULL;
}
/*
@@ -269,14 +281,15 @@ event_add(struct event *ev, struct timeval *tv)
if (tv != NULL) {
struct timeval now;
+ if (ev->ev_flags & EVLIST_TIMEOUT)
+ event_queue_remove(ev, EVLIST_TIMEOUT);
+
gettimeofday(&now, NULL);
timeradd(&now, tv, &ev->ev_timeout);
LOG_DBG((LOG_MISC, 55,
"event_add: timeout in %d seconds, call %p",
tv->tv_sec, ev->ev_callback));
- if (ev->ev_flags & EVLIST_TIMEOUT)
- event_queue_remove(ev, EVLIST_TIMEOUT);
event_queue_insert(ev, EVLIST_TIMEOUT);
}
@@ -286,6 +299,11 @@ event_add(struct event *ev, struct timeval *tv)
event_queue_insert(ev, EVLIST_INSERTED);
return (evsel->add(evbase, ev));
+ } else if ((ev->ev_events & EV_SIGNAL) &&
+ !(ev->ev_flags & EVLIST_SIGNAL)) {
+ event_queue_insert(ev, EVLIST_SIGNAL);
+
+ return (evsel->add(evbase, ev));
}
return (0);
@@ -299,6 +317,12 @@ event_del(struct event *ev)
assert(!(ev->ev_flags & ~EVLIST_ALL));
+ /* See if we are just active executing this event in a loop */
+ if (ev->ev_ncalls && ev->ev_pncalls) {
+ /* Abort loop */
+ *ev->ev_pncalls = 0;
+ }
+
if (ev->ev_flags & EVLIST_TIMEOUT)
event_queue_remove(ev, EVLIST_TIMEOUT);
@@ -308,27 +332,39 @@ event_del(struct event *ev)
if (ev->ev_flags & EVLIST_INSERTED) {
event_queue_remove(ev, EVLIST_INSERTED);
return (evsel->del(evbase, ev));
+ } else if (ev->ev_flags & EVLIST_SIGNAL) {
+ event_queue_remove(ev, EVLIST_SIGNAL);
+ return (evsel->del(evbase, ev));
}
return (0);
}
void
-event_active(struct event *ev, int res)
+event_active(struct event *ev, int res, short ncalls)
{
+ /* We get different kinds of events, add them together */
+ if (ev->ev_flags & EVLIST_ACTIVE) {
+ ev->ev_res |= res;
+ return;
+ }
+
ev->ev_res = res;
+ ev->ev_ncalls = ncalls;
+ ev->ev_pncalls = NULL;
event_queue_insert(ev, EVLIST_ACTIVE);
}
int
timeout_next(struct timeval *tv)
{
+ struct timeval dflt = TIMEOUT_DEFAULT;
+
struct timeval now;
struct event *ev;
if ((ev = RB_MIN(event_tree, &timetree)) == NULL) {
- timerclear(tv);
- tv->tv_sec = TIMEOUT_DEFAULT;
+ *tv = dflt;
return (0);
}
@@ -378,7 +414,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);
}
}
@@ -419,6 +455,9 @@ event_queue_remove(struct event *ev, int queue)
case EVLIST_ACTIVE:
TAILQ_REMOVE(&activequeue, ev, ev_active_next);
break;
+ case EVLIST_SIGNAL:
+ TAILQ_REMOVE(&signalqueue, ev, ev_signal_next);
+ break;
case EVLIST_TIMEOUT:
RB_REMOVE(event_tree, &timetree, ev);
break;
@@ -442,6 +481,9 @@ event_queue_insert(struct event *ev, int queue)
case EVLIST_ACTIVE:
TAILQ_INSERT_TAIL(&activequeue, ev, ev_active_next);
break;
+ case EVLIST_SIGNAL:
+ TAILQ_INSERT_TAIL(&signalqueue, ev, ev_signal_next);
+ break;
case EVLIST_TIMEOUT:
timeout_insert(ev);
break;
View
20 kame/kame/faithd.libevent/event.h
@@ -36,6 +36,7 @@ extern "C" {
#define EVLIST_TIMEOUT 0x01
#define EVLIST_INSERTED 0x02
+#define EVLIST_SIGNAL 0x04
#define EVLIST_ACTIVE 0x08
#define EVLIST_INIT 0x80
@@ -45,6 +46,8 @@ extern "C" {
#define EV_TIMEOUT 0x01
#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
@@ -69,10 +72,13 @@ struct { \
struct event {
TAILQ_ENTRY (event) ev_next;
TAILQ_ENTRY (event) ev_active_next;
+ TAILQ_ENTRY (event) ev_signal_next;
RB_ENTRY (event) ev_timeout_node;
int ev_fd;
short ev_events;
+ short ev_ncalls;
+ short *ev_pncalls; /* Allows deletes in callback */
struct timeval ev_timeout;
@@ -83,6 +89,9 @@ struct event {
int ev_flags;
};
+#define EVENT_SIGNAL(ev) ev->ev_fd
+#define EVENT_FD(ev) ev->ev_fd
+
#ifdef _EVENT_DEFINED_TQENTRY
#undef TAILQ_ENTRY
#undef _EVENT_DEFINED_TQENTRY
@@ -103,7 +112,7 @@ struct eventop {
int (*dispatch)(void *, struct timeval *);
};
-#define TIMEOUT_DEFAULT 5
+#define TIMEOUT_DEFAULT {5, 0}
void event_init(void);
int event_dispatch(void);
@@ -122,10 +131,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
110 kame/kame/faithd.libevent/select.c
@@ -32,11 +32,13 @@
#include <sys/types.h>
#include <sys/time.h>
#include <sys/queue.h>
+#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
+#include <err.h>
#ifdef USE_LOG
#include "log.h"
@@ -49,19 +51,26 @@
extern struct event_list timequeue;
extern struct event_list eventqueue;
-extern struct event_list addqueue;
+extern struct event_list signalqueue;
#ifndef howmany
#define howmany(x, y) (((x)+((y)-1))/(y))
#endif
+short evsigcaught[NSIG];
+
struct selectop {
int event_fds; /* Highest fd in fd set */
int event_fdsz;
fd_set *event_readset;
fd_set *event_writeset;
+ sigset_t evsigmask;
} sop;
+void signal_process(void);
+int signal_recalc(void);
+int signal_deliver(void);
+
void *select_init (void);
int select_add (void *, struct event *);
int select_del (void *, struct event *);
@@ -82,6 +91,8 @@ select_init(void)
{
memset(&sop, 0, sizeof(sop));
+ sigemptyset(&sop.evsigmask);
+
return (&sop);
}
@@ -130,7 +141,7 @@ select_recalc(void *arg, int max)
sop->event_fdsz = fdsz;
}
- return (0);
+ return (signal_recalc());
}
int
@@ -150,14 +161,22 @@ select_dispatch(void *arg, struct timeval *tv)
FD_SET(ev->ev_fd, sop->event_readset);
}
+ if (signal_deliver() == -1)
+ return (-1);
+
+ res = select(sop->event_fds + 1, sop->event_readset,
+ sop->event_writeset, NULL, tv);
+
+ if (signal_recalc() == -1)
+ return (-1);
- if ((res = select(sop->event_fds + 1, sop->event_readset,
- sop->event_writeset, NULL, tv)) == -1) {
+ if (res == -1) {
if (errno != EINTR) {
log_error("select");
return (-1);
}
-
+
+ signal_process();
return (0);
}
@@ -176,8 +195,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;
}
@@ -192,6 +212,18 @@ select_add(void *arg, struct event *ev)
{
struct selectop *sop = arg;
+ if (ev->ev_events & EV_SIGNAL) {
+ int signal;
+
+ if (ev->ev_events & (EV_READ|EV_WRITE))
+ errx(1, "%s: EV_SIGNAL incompatible use",
+ __FUNCTION__);
+ signal = EVENT_SIGNAL(ev);
+ sigaddset(&sop->evsigmask, signal);
+
+ return (0);
+ }
+
/*
* Keep track of the highest fd, so that we can calculate the size
* of the fd_sets for select(2)
@@ -209,5 +241,69 @@ select_add(void *arg, struct event *ev)
int
select_del(void *arg, struct event *ev)
{
+ struct selectop *sop = arg;
+
+ int signal;
+
+ if (!(ev->ev_events & EV_SIGNAL))
+ return (0);
+
+ signal = EVENT_SIGNAL(ev);
+ sigdelset(&sop->evsigmask, signal);
+
+ return (sigaction(EVENT_SIGNAL(ev),(struct sigaction *)SIG_DFL, NULL));
+}
+
+static void
+signal_handler(int sig)
+{
+ evsigcaught[sig]++;
+}
+
+int
+signal_recalc(void)
+{
+ struct sigaction sa;
+ struct event *ev;
+
+ if (sigprocmask(SIG_BLOCK, &sop.evsigmask, NULL) == -1)
+ return (-1);
+
+ /* Reinstall our signal handler. */
+ memset(&sa, 0, sizeof(sa));
+ sa.sa_handler = signal_handler;
+ sa.sa_mask = sop.evsigmask;
+ sa.sa_flags |= SA_RESTART;
+
+ TAILQ_FOREACH(ev, &signalqueue, ev_signal_next) {
+ if (sigaction(EVENT_SIGNAL(ev), &sa, NULL) == -1)
+ return (-1);
+ }
return (0);
}
+
+int
+signal_deliver(void)
+{
+ return (sigprocmask(SIG_UNBLOCK, &sop.evsigmask, NULL));
+ /* XXX - pending signals handled here */
+}
+
+void
+signal_process(void)
+{
+ struct event *ev;
+ short ncalls;
+
+ TAILQ_FOREACH(ev, &signalqueue, ev_signal_next) {
+ 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));
+}
+
Please sign in to comment.
Something went wrong with that request. Please try again.