mirror of
https://github.com/cuberite/libevent.git
synced 2025-09-13 06:16:10 -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 RB_HEAD(event_tree, event) timetree;
|
||||||
static struct event_list activequeue;
|
static struct event_list activequeue;
|
||||||
|
struct event_list signalqueue;
|
||||||
struct event_list eventqueue;
|
struct event_list eventqueue;
|
||||||
static struct timeval event_tv;
|
static struct timeval event_tv;
|
||||||
|
|
||||||
@ -111,6 +112,7 @@ event_init(void)
|
|||||||
RB_INIT(&timetree);
|
RB_INIT(&timetree);
|
||||||
TAILQ_INIT(&eventqueue);
|
TAILQ_INIT(&eventqueue);
|
||||||
TAILQ_INIT(&activequeue);
|
TAILQ_INIT(&activequeue);
|
||||||
|
TAILQ_INIT(&signalqueue);
|
||||||
|
|
||||||
evbase = NULL;
|
evbase = NULL;
|
||||||
for (i = 0; eventops[i] && !evbase; i++) {
|
for (i = 0; eventops[i] && !evbase; i++) {
|
||||||
@ -129,7 +131,7 @@ int
|
|||||||
event_haveevents(void)
|
event_haveevents(void)
|
||||||
{
|
{
|
||||||
return (RB_ROOT(&timetree) || TAILQ_FIRST(&eventqueue) ||
|
return (RB_ROOT(&timetree) || TAILQ_FIRST(&eventqueue) ||
|
||||||
TAILQ_FIRST(&activequeue));
|
TAILQ_FIRST(&signalqueue) || TAILQ_FIRST(&activequeue));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -285,6 +287,11 @@ event_add(struct event *ev, struct timeval *tv)
|
|||||||
!(ev->ev_flags & EVLIST_INSERTED)) {
|
!(ev->ev_flags & EVLIST_INSERTED)) {
|
||||||
event_queue_insert(ev, 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));
|
return (evsel->add(evbase, ev));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -308,6 +315,9 @@ event_del(struct event *ev)
|
|||||||
if (ev->ev_flags & EVLIST_INSERTED) {
|
if (ev->ev_flags & EVLIST_INSERTED) {
|
||||||
event_queue_remove(ev, EVLIST_INSERTED);
|
event_queue_remove(ev, EVLIST_INSERTED);
|
||||||
return (evsel->del(evbase, ev));
|
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);
|
return (0);
|
||||||
@ -323,12 +333,13 @@ event_active(struct event *ev, int res)
|
|||||||
int
|
int
|
||||||
timeout_next(struct timeval *tv)
|
timeout_next(struct timeval *tv)
|
||||||
{
|
{
|
||||||
|
struct timeval dflt = TIMEOUT_DEFAULT;
|
||||||
|
|
||||||
struct timeval now;
|
struct timeval now;
|
||||||
struct event *ev;
|
struct event *ev;
|
||||||
|
|
||||||
if ((ev = RB_MIN(event_tree, &timetree)) == NULL) {
|
if ((ev = RB_MIN(event_tree, &timetree)) == NULL) {
|
||||||
timerclear(tv);
|
*tv = dflt;
|
||||||
tv->tv_sec = TIMEOUT_DEFAULT;
|
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -419,6 +430,9 @@ event_queue_remove(struct event *ev, int queue)
|
|||||||
case EVLIST_ACTIVE:
|
case EVLIST_ACTIVE:
|
||||||
TAILQ_REMOVE(&activequeue, ev, ev_active_next);
|
TAILQ_REMOVE(&activequeue, ev, ev_active_next);
|
||||||
break;
|
break;
|
||||||
|
case EVLIST_SIGNAL:
|
||||||
|
TAILQ_REMOVE(&signalqueue, ev, ev_signal_next);
|
||||||
|
break;
|
||||||
case EVLIST_TIMEOUT:
|
case EVLIST_TIMEOUT:
|
||||||
RB_REMOVE(event_tree, &timetree, ev);
|
RB_REMOVE(event_tree, &timetree, ev);
|
||||||
break;
|
break;
|
||||||
@ -442,6 +456,9 @@ event_queue_insert(struct event *ev, int queue)
|
|||||||
case EVLIST_ACTIVE:
|
case EVLIST_ACTIVE:
|
||||||
TAILQ_INSERT_TAIL(&activequeue, ev, ev_active_next);
|
TAILQ_INSERT_TAIL(&activequeue, ev, ev_active_next);
|
||||||
break;
|
break;
|
||||||
|
case EVLIST_SIGNAL:
|
||||||
|
TAILQ_INSERT_TAIL(&signalqueue, ev, ev_signal_next);
|
||||||
|
break;
|
||||||
case EVLIST_TIMEOUT:
|
case EVLIST_TIMEOUT:
|
||||||
timeout_insert(ev);
|
timeout_insert(ev);
|
||||||
break;
|
break;
|
||||||
|
8
event.h
8
event.h
@ -36,6 +36,7 @@ extern "C" {
|
|||||||
|
|
||||||
#define EVLIST_TIMEOUT 0x01
|
#define EVLIST_TIMEOUT 0x01
|
||||||
#define EVLIST_INSERTED 0x02
|
#define EVLIST_INSERTED 0x02
|
||||||
|
#define EVLIST_SIGNAL 0x04
|
||||||
#define EVLIST_ACTIVE 0x08
|
#define EVLIST_ACTIVE 0x08
|
||||||
#define EVLIST_INIT 0x80
|
#define EVLIST_INIT 0x80
|
||||||
|
|
||||||
@ -45,6 +46,7 @@ extern "C" {
|
|||||||
#define EV_TIMEOUT 0x01
|
#define EV_TIMEOUT 0x01
|
||||||
#define EV_READ 0x02
|
#define EV_READ 0x02
|
||||||
#define EV_WRITE 0x04
|
#define EV_WRITE 0x04
|
||||||
|
#define EV_SIGNAL 0x08
|
||||||
|
|
||||||
/* Fix so that ppl dont have to run with <sys/queue.h> */
|
/* Fix so that ppl dont have to run with <sys/queue.h> */
|
||||||
#ifndef TAILQ_ENTRY
|
#ifndef TAILQ_ENTRY
|
||||||
@ -69,6 +71,7 @@ struct { \
|
|||||||
struct event {
|
struct event {
|
||||||
TAILQ_ENTRY (event) ev_next;
|
TAILQ_ENTRY (event) ev_next;
|
||||||
TAILQ_ENTRY (event) ev_active_next;
|
TAILQ_ENTRY (event) ev_active_next;
|
||||||
|
TAILQ_ENTRY (event) ev_signal_next;
|
||||||
RB_ENTRY (event) ev_timeout_node;
|
RB_ENTRY (event) ev_timeout_node;
|
||||||
|
|
||||||
int ev_fd;
|
int ev_fd;
|
||||||
@ -83,6 +86,9 @@ struct event {
|
|||||||
int ev_flags;
|
int ev_flags;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define EVENT_SIGNAL(ev) ev->ev_fd
|
||||||
|
#define EVENT_FD(ev) ev->ev_fd
|
||||||
|
|
||||||
#ifdef _EVENT_DEFINED_TQENTRY
|
#ifdef _EVENT_DEFINED_TQENTRY
|
||||||
#undef TAILQ_ENTRY
|
#undef TAILQ_ENTRY
|
||||||
#undef _EVENT_DEFINED_TQENTRY
|
#undef _EVENT_DEFINED_TQENTRY
|
||||||
@ -103,7 +109,7 @@ struct eventop {
|
|||||||
int (*dispatch)(void *, struct timeval *);
|
int (*dispatch)(void *, struct timeval *);
|
||||||
};
|
};
|
||||||
|
|
||||||
#define TIMEOUT_DEFAULT 5
|
#define TIMEOUT_DEFAULT {0, 250000L}
|
||||||
|
|
||||||
void event_init(void);
|
void event_init(void);
|
||||||
int event_dispatch(void);
|
int event_dispatch(void);
|
||||||
|
@ -3,9 +3,10 @@ AUTOMAKE_OPTIONS = foreign no-dependencies
|
|||||||
LDADD = -L.. -levent
|
LDADD = -L.. -levent
|
||||||
CPPFPLAGS = -I..
|
CPPFPLAGS = -I..
|
||||||
|
|
||||||
noinst_PROGRAMS = event-test time-test
|
noinst_PROGRAMS = event-test time-test signal-test
|
||||||
|
|
||||||
event_test_sources = event-test.c
|
event_test_sources = event-test.c
|
||||||
time_test_sources = time-test.c
|
time_test_sources = time-test.c
|
||||||
|
signal_test_sources = signal-test.c
|
||||||
|
|
||||||
DISTCLEANFILES = *~
|
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/types.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <sys/queue.h>
|
#include <sys/queue.h>
|
||||||
|
#include <signal.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@ -49,19 +50,25 @@
|
|||||||
|
|
||||||
extern struct event_list timequeue;
|
extern struct event_list timequeue;
|
||||||
extern struct event_list eventqueue;
|
extern struct event_list eventqueue;
|
||||||
extern struct event_list addqueue;
|
extern struct event_list signalqueue;
|
||||||
|
|
||||||
#ifndef howmany
|
#ifndef howmany
|
||||||
#define howmany(x, y) (((x)+((y)-1))/(y))
|
#define howmany(x, y) (((x)+((y)-1))/(y))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
int evsigcaught[NSIG];
|
||||||
|
|
||||||
struct selectop {
|
struct selectop {
|
||||||
int event_fds; /* Highest fd in fd set */
|
int event_fds; /* Highest fd in fd set */
|
||||||
int event_fdsz;
|
int event_fdsz;
|
||||||
fd_set *event_readset;
|
fd_set *event_readset;
|
||||||
fd_set *event_writeset;
|
fd_set *event_writeset;
|
||||||
|
sigset_t evsigmask;
|
||||||
} sop;
|
} sop;
|
||||||
|
|
||||||
|
void signal_process(void);
|
||||||
|
int signal_recalc(void);
|
||||||
|
|
||||||
void *select_init (void);
|
void *select_init (void);
|
||||||
int select_add (void *, struct event *);
|
int select_add (void *, struct event *);
|
||||||
int select_del (void *, struct event *);
|
int select_del (void *, struct event *);
|
||||||
@ -82,6 +89,8 @@ select_init(void)
|
|||||||
{
|
{
|
||||||
memset(&sop, 0, sizeof(sop));
|
memset(&sop, 0, sizeof(sop));
|
||||||
|
|
||||||
|
sigemptyset(&sop.evsigmask);
|
||||||
|
|
||||||
return (&sop);
|
return (&sop);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -130,7 +139,7 @@ select_recalc(void *arg, int max)
|
|||||||
sop->event_fdsz = fdsz;
|
sop->event_fdsz = fdsz;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (0);
|
return (signal_recalc());
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
@ -150,9 +159,16 @@ select_dispatch(void *arg, struct timeval *tv)
|
|||||||
FD_SET(ev->ev_fd, sop->event_readset);
|
FD_SET(ev->ev_fd, sop->event_readset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (signal_deliver() == -1)
|
||||||
|
return (-1);
|
||||||
|
|
||||||
if ((res = select(sop->event_fds + 1, sop->event_readset,
|
res = select(sop->event_fds + 1, sop->event_readset,
|
||||||
sop->event_writeset, NULL, tv)) == -1) {
|
sop->event_writeset, NULL, tv);
|
||||||
|
|
||||||
|
if (signal_recalc() == -1)
|
||||||
|
return (-1);
|
||||||
|
|
||||||
|
if (res == -1) {
|
||||||
if (errno != EINTR) {
|
if (errno != EINTR) {
|
||||||
log_error("select");
|
log_error("select");
|
||||||
return (-1);
|
return (-1);
|
||||||
@ -184,6 +200,8 @@ select_dispatch(void *arg, struct timeval *tv)
|
|||||||
|
|
||||||
sop->event_fds = maxfd;
|
sop->event_fds = maxfd;
|
||||||
|
|
||||||
|
signal_process();
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -192,6 +210,18 @@ select_add(void *arg, struct event *ev)
|
|||||||
{
|
{
|
||||||
struct selectop *sop = arg;
|
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
|
* Keep track of the highest fd, so that we can calculate the size
|
||||||
* of the fd_sets for select(2)
|
* of the fd_sets for select(2)
|
||||||
@ -209,5 +239,64 @@ select_add(void *arg, struct event *ev)
|
|||||||
int
|
int
|
||||||
select_del(void *arg, struct event *ev)
|
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);
|
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