mirror of
https://github.com/cuberite/libevent.git
synced 2025-09-12 13:58:58 -04:00
initial support for signals (only for select now) based on code from
Dug Song <dugsong@monkey.org> svn:r17
This commit is contained in:
parent
dbaa408ea5
commit
b855bc5500
23
event.c
23
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,7 +131,7 @@ int
|
||||
event_haveevents(void)
|
||||
{
|
||||
return (RB_ROOT(&timetree) || TAILQ_FIRST(&eventqueue) ||
|
||||
TAILQ_FIRST(&activequeue));
|
||||
TAILQ_FIRST(&signalqueue) || TAILQ_FIRST(&activequeue));
|
||||
}
|
||||
|
||||
void
|
||||
@ -285,6 +287,11 @@ event_add(struct event *ev, struct timeval *tv)
|
||||
!(ev->ev_flags & EVLIST_INSERTED)) {
|
||||
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));
|
||||
}
|
||||
|
||||
@ -308,6 +315,9 @@ 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);
|
||||
@ -323,12 +333,13 @@ event_active(struct event *ev, int res)
|
||||
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);
|
||||
}
|
||||
|
||||
@ -419,6 +430,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 +456,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;
|
||||
|
8
event.h
8
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,7 @@ extern "C" {
|
||||
#define EV_TIMEOUT 0x01
|
||||
#define EV_READ 0x02
|
||||
#define EV_WRITE 0x04
|
||||
#define EV_SIGNAL 0x08
|
||||
|
||||
/* Fix so that ppl dont have to run with <sys/queue.h> */
|
||||
#ifndef TAILQ_ENTRY
|
||||
@ -69,6 +71,7 @@ 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;
|
||||
@ -83,6 +86,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 +109,7 @@ struct eventop {
|
||||
int (*dispatch)(void *, struct timeval *);
|
||||
};
|
||||
|
||||
#define TIMEOUT_DEFAULT 5
|
||||
#define TIMEOUT_DEFAULT {0, 250000L}
|
||||
|
||||
void event_init(void);
|
||||
int event_dispatch(void);
|
||||
|
@ -3,9 +3,10 @@ AUTOMAKE_OPTIONS = foreign no-dependencies
|
||||
LDADD = -L.. -levent
|
||||
CPPFPLAGS = -I..
|
||||
|
||||
noinst_PROGRAMS = event-test time-test
|
||||
noinst_PROGRAMS = event-test time-test signal-test
|
||||
|
||||
event_test_sources = event-test.c
|
||||
time_test_sources = time-test.c
|
||||
signal_test_sources = signal-test.c
|
||||
|
||||
DISTCLEANFILES = *~
|
||||
|
52
sample/signal-test.c
Normal file
52
sample/signal-test.c
Normal file
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Compile with:
|
||||
* cc -I/usr/local/include -o time-test time-test.c -L/usr/local/lib -levent
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/queue.h>
|
||||
#include <sys/time.h>
|
||||
#include <signal.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <event.h>
|
||||
|
||||
int called = 0;
|
||||
|
||||
void
|
||||
signal_cb(int fd, short event, void *arg)
|
||||
{
|
||||
struct event *signal = arg;
|
||||
|
||||
printf("%s: got signal %d\n", __FUNCTION__, EVENT_SIGNAL(signal));
|
||||
|
||||
if (called >= 2)
|
||||
event_del(signal);
|
||||
|
||||
called++;
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
struct event signal_int;
|
||||
|
||||
/* Initalize the event library */
|
||||
event_init();
|
||||
|
||||
/* Initalize one event */
|
||||
event_set(&signal_int, SIGINT, EV_SIGNAL, signal_cb, &signal_int);
|
||||
|
||||
event_add(&signal_int, NULL);
|
||||
|
||||
event_dispatch();
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
97
select.c
97
select.c
@ -32,6 +32,7 @@
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/queue.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@ -49,19 +50,25 @@
|
||||
|
||||
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
|
||||
|
||||
int 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);
|
||||
|
||||
void *select_init (void);
|
||||
int select_add (void *, struct event *);
|
||||
int select_del (void *, struct event *);
|
||||
@ -82,6 +89,8 @@ select_init(void)
|
||||
{
|
||||
memset(&sop, 0, sizeof(sop));
|
||||
|
||||
sigemptyset(&sop.evsigmask);
|
||||
|
||||
return (&sop);
|
||||
}
|
||||
|
||||
@ -130,7 +139,7 @@ select_recalc(void *arg, int max)
|
||||
sop->event_fdsz = fdsz;
|
||||
}
|
||||
|
||||
return (0);
|
||||
return (signal_recalc());
|
||||
}
|
||||
|
||||
int
|
||||
@ -150,9 +159,16 @@ select_dispatch(void *arg, struct timeval *tv)
|
||||
FD_SET(ev->ev_fd, sop->event_readset);
|
||||
}
|
||||
|
||||
if (signal_deliver() == -1)
|
||||
return (-1);
|
||||
|
||||
if ((res = select(sop->event_fds + 1, sop->event_readset,
|
||||
sop->event_writeset, NULL, tv)) == -1) {
|
||||
res = select(sop->event_fds + 1, sop->event_readset,
|
||||
sop->event_writeset, NULL, tv);
|
||||
|
||||
if (signal_recalc() == -1)
|
||||
return (-1);
|
||||
|
||||
if (res == -1) {
|
||||
if (errno != EINTR) {
|
||||
log_error("select");
|
||||
return (-1);
|
||||
@ -184,6 +200,8 @@ select_dispatch(void *arg, struct timeval *tv)
|
||||
|
||||
sop->event_fds = maxfd;
|
||||
|
||||
signal_process();
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -192,6 +210,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 +239,64 @@ 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;
|
||||
|
||||
TAILQ_FOREACH(ev, &signalqueue, ev_signal_next) {
|
||||
if (evsigcaught[EVENT_SIGNAL(ev)])
|
||||
event_active(ev, EV_SIGNAL);
|
||||
}
|
||||
|
||||
memset(evsigcaught, 0, sizeof(evsigcaught));
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user