more the signal base into the event base; this removes global state and makes signals

work better with threading; from Wouter Wijngaards
small fixes for kqueue and style by me


svn:r351
This commit is contained in:
Niels Provos 2007-03-10 06:37:53 +00:00
parent a968da7425
commit 41b7cbc381
15 changed files with 270 additions and 124 deletions

View File

@ -81,12 +81,12 @@ struct win32op {
struct event **events;
};
void *win32_init (void);
void *win32_init (struct event_base *);
int win32_insert (void *, struct event *);
int win32_del (void *, struct event *);
int win32_recalc (struct event_base *base, void *, int);
int win32_dispatch (struct event_base *base, void *, struct timeval *);
void win32_dealloc (void *);
void win32_dealloc (struct event_base *, void *);
struct eventop win32ops = {
"win32",
@ -167,7 +167,7 @@ do_fd_clear(struct win32op *op, SOCKET s, int read)
#define NEVENT 64
void *
win32_init(void)
win32_init(struct event_base *)
{
struct win32op *winop;
size_t size;
@ -376,7 +376,7 @@ win32_dispatch(struct event_base *base, void *op,
}
void
win32_dealloc(void *arg)
win32_dealloc(struct event_base *, void *arg)
{
struct win32op *win32op = arg;

View File

@ -50,8 +50,6 @@
#include "evsignal.h"
#include "log.h"
extern volatile sig_atomic_t evsignal_caught;
/* due to limitations in the devpoll interface, we need to keep track of
* all file descriptors outself.
*/
@ -70,12 +68,12 @@ struct devpollop {
int nchanges;
};
void *devpoll_init (void);
void *devpoll_init (struct event_base *);
int devpoll_add (void *, struct event *);
int devpoll_del (void *, struct event *);
int devpoll_recalc (struct event_base *, void *, int);
int devpoll_dispatch (struct event_base *, void *, struct timeval *);
void devpoll_dealloc (void *);
void devpoll_dealloc (struct event_base *, void *);
struct eventop devpollops = {
"devpoll",
@ -126,7 +124,7 @@ devpoll_queue(struct devpollop *devpollop, int fd, int events) {
}
void *
devpoll_init(void)
devpoll_init(struct event_base *base)
{
int dpfd, nfiles = NEVENT;
struct rlimit rl;
@ -179,7 +177,7 @@ devpoll_init(void)
return (NULL);
}
evsignal_init();
evsignal_init(base);
return (devpollop);
}
@ -237,10 +235,11 @@ devpoll_dispatch(struct event_base *base, void *arg, struct timeval *tv)
return (-1);
}
evsignal_process();
evsignal_process(base);
return (0);
} else if (evsignal_caught)
evsignal_process();
} else if (base->sig.evsignal_caught) {
evsignal_process(base);
}
event_debug(("%s: devpoll_wait reports %d", __func__, res));
@ -398,10 +397,11 @@ devpoll_del(void *arg, struct event *ev)
}
void
devpoll_dealloc(void *arg)
devpoll_dealloc(struct event_base *base, void *arg)
{
struct devpollop *devpollop = arg;
evsignal_dealloc(base);
if (devpollop->fds)
free(devpollop->fds);
if (devpollop->events)

22
epoll.c
View File

@ -30,6 +30,7 @@
#include <stdint.h>
#include <sys/types.h>
#include <sys/tree.h>
#include <sys/resource.h>
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
@ -49,11 +50,10 @@
#endif
#include "event.h"
#include "event-internal.h"
#include "evsignal.h"
#include "log.h"
extern volatile sig_atomic_t evsignal_caught;
/* due to limitations in the epoll interface, we need to keep track of
* all file descriptors outself.
*/
@ -70,12 +70,12 @@ struct epollop {
int epfd;
};
void *epoll_init (void);
void *epoll_init (struct event_base *);
int epoll_add (void *, struct event *);
int epoll_del (void *, struct event *);
int epoll_recalc (struct event_base *, void *, int);
int epoll_dispatch (struct event_base *, void *, struct timeval *);
void epoll_dealloc (void *);
void epoll_dealloc (struct event_base *, void *);
struct eventop epollops = {
"epoll",
@ -99,7 +99,7 @@ struct eventop epollops = {
#define NEVENT 32000
void *
epoll_init(void)
epoll_init(struct event_base *base)
{
int epfd, nfiles = NEVENT;
struct rlimit rl;
@ -149,7 +149,7 @@ epoll_init(void)
}
epollop->nfds = nfiles;
evsignal_init();
evsignal_init(base);
return (epollop);
}
@ -198,10 +198,11 @@ epoll_dispatch(struct event_base *base, void *arg, struct timeval *tv)
return (-1);
}
evsignal_process();
evsignal_process(base);
return (0);
} else if (evsignal_caught)
evsignal_process();
} else if (base->sig.evsignal_caught) {
evsignal_process(base);
}
event_debug(("%s: epoll_wait reports %d", __func__, res));
@ -346,10 +347,11 @@ epoll_del(void *arg, struct event *ev)
}
void
epoll_dealloc(void *arg)
epoll_dealloc(struct event_base *base, void *arg)
{
struct epollop *epollop = arg;
evsignal_dealloc(base);
if (epollop->fds)
free(epollop->fds);
if (epollop->events)

View File

@ -31,6 +31,8 @@
extern "C" {
#endif
#include "evsignal.h"
struct event_base {
const struct eventop *evsel;
void *evbase;
@ -43,6 +45,9 @@ struct event_base {
struct event_list **activequeues;
int nactivequeues;
/* signal handling info */
struct evsignal_info sig;
struct event_list eventqueue;
struct timeval event_tv;

View File

@ -42,6 +42,7 @@
.Nm event_add ,
.Nm event_del ,
.Nm event_once ,
.Nm event_base_once ,
.Nm event_pending ,
.Nm event_initialized ,
.Nm event_priority_init ,
@ -107,6 +108,8 @@
.Ft int
.Fn "event_once" "int fd" "short event" "void (*fn)(int, short, void *)" "void *arg" "struct timeval *tv"
.Ft int
.Fn "event_base_once" "struct event_base *base" "int fd" "short event" "void (*fn)(int, short, void *)" "void *arg" "struct timeval *tv"
.Ft int
.Fn "event_pending" "struct event *ev" "short event" "struct timeval *tv"
.Ft int
.Fn "event_initialized" "struct event *ev"

63
event.c
View File

@ -111,9 +111,8 @@ const struct eventop *eventops[] = {
};
/* Global state */
struct event_list signalqueue;
struct event_base *current_base = NULL;
extern struct event_base *evsignal_base;
/* Handle signals - This is a deprecated interface */
int (*event_sigcb)(void); /* Signal callback when gotsig is set */
@ -174,36 +173,40 @@ void *
event_init(void)
{
int i;
struct event_base *base;
if ((current_base = calloc(1, sizeof(struct event_base))) == NULL)
if ((base = calloc(1, sizeof(struct event_base))) == NULL)
event_err(1, "%s: calloc");
event_sigcb = NULL;
event_gotsig = 0;
gettime(&current_base->event_tv);
gettime(&base->event_tv);
RB_INIT(&current_base->timetree);
TAILQ_INIT(&current_base->eventqueue);
TAILQ_INIT(&signalqueue);
RB_INIT(&base->timetree);
TAILQ_INIT(&base->eventqueue);
TAILQ_INIT(&base->sig.signalqueue);
base->sig.ev_signal_pair[0] = -1;
base->sig.ev_signal_pair[1] = -1;
current_base->evbase = NULL;
for (i = 0; eventops[i] && !current_base->evbase; i++) {
current_base->evsel = eventops[i];
base->evbase = NULL;
for (i = 0; eventops[i] && !base->evbase; i++) {
base->evsel = eventops[i];
current_base->evbase = current_base->evsel->init();
base->evbase = base->evsel->init(base);
}
if (current_base->evbase == NULL)
if (base->evbase == NULL)
event_errx(1, "%s: no event mechanism available", __func__);
if (getenv("EVENT_SHOW_METHOD"))
event_msgx("libevent using: %s\n",
current_base->evsel->name);
base->evsel->name);
/* allocate a single active event queue */
event_base_priority_init(current_base, 1);
event_base_priority_init(base, 1);
return (current_base);
current_base = base;
return (base);
}
void
@ -217,7 +220,8 @@ event_base_free(struct event_base *base)
current_base = NULL;
assert(base);
assert(TAILQ_EMPTY(&base->eventqueue));
if (base->evsel->dealloc != NULL)
base->evsel->dealloc(base, base->evbase);
for (i=0; i < base->nactivequeues; ++i)
assert(TAILQ_EMPTY(base->activequeues[i]));
@ -227,8 +231,7 @@ event_base_free(struct event_base *base)
free(base->activequeues[i]);
free(base->activequeues);
if (base->evsel->dealloc != NULL)
base->evsel->dealloc(base->evbase);
assert(TAILQ_EMPTY(&base->eventqueue));
free(base);
}
@ -343,7 +346,6 @@ event_loopexit_cb(int fd, short what, void *arg)
}
/* not thread safe */
int
event_loopexit(struct timeval *tv)
{
@ -354,7 +356,7 @@ event_loopexit(struct timeval *tv)
int
event_base_loopexit(struct event_base *event_base, struct timeval *tv)
{
return (event_once(-1, EV_TIMEOUT, event_loopexit_cb,
return (event_base_once(event_base, -1, EV_TIMEOUT, event_loopexit_cb,
event_base, tv));
}
@ -374,6 +376,8 @@ event_base_loop(struct event_base *base, int flags)
struct timeval tv;
int res, done;
if(!TAILQ_EMPTY(&base->sig.signalqueue))
evsignal_base = base;
done = 0;
while (!done) {
/* Calculate the initial events that we are waiting for */
@ -422,6 +426,7 @@ event_base_loop(struct event_base *base, int flags)
res = evsel->dispatch(base, evbase, &tv);
if (res == -1)
return (-1);
@ -459,11 +464,18 @@ event_once_cb(int fd, short events, void *arg)
free(eonce);
}
/* Schedules an event once */
/* not threadsafe, event scheduled once. */
int
event_once(int fd, short events,
void (*callback)(int, short, void *), void *arg, struct timeval *tv)
{
return event_base_once(current_base, fd, events, callback, arg, tv);
}
/* Schedules an event once */
int
event_base_once(struct event_base *base, int fd, short events,
void (*callback)(int, short, void *), void *arg, struct timeval *tv)
{
struct event_once *eonce;
struct timeval etv;
@ -496,6 +508,8 @@ event_once(int fd, short events,
return (-1);
}
res = event_base_set(base, &eonce->ev);
if (res == 0)
res = event_add(&eonce->ev, tv);
if (res != 0) {
free(eonce);
@ -521,6 +535,7 @@ event_set(struct event *ev, int fd, short events,
ev->ev_pncalls = NULL;
/* by default, we put new events into the middle priority */
if(current_base)
ev->ev_pri = current_base->nactivequeues/2;
}
@ -801,7 +816,7 @@ event_queue_remove(struct event_base *base, struct event *ev, int queue)
ev, ev_active_next);
break;
case EVLIST_SIGNAL:
TAILQ_REMOVE(&signalqueue, ev, ev_signal_next);
TAILQ_REMOVE(&base->sig.signalqueue, ev, ev_signal_next);
break;
case EVLIST_TIMEOUT:
RB_REMOVE(event_tree, &base->timetree, ev);
@ -843,7 +858,7 @@ event_queue_insert(struct event_base *base, struct event *ev, int queue)
ev,ev_active_next);
break;
case EVLIST_SIGNAL:
TAILQ_INSERT_TAIL(&signalqueue, ev, ev_signal_next);
TAILQ_INSERT_TAIL(&base->sig.signalqueue, ev, ev_signal_next);
break;
case EVLIST_TIMEOUT: {
struct event *tmp = RB_INSERT(event_tree, &base->timetree, ev);

View File

@ -131,12 +131,12 @@ TAILQ_HEAD (evkeyvalq, evkeyval);
struct eventop {
char *name;
void *(*init)(void);
void *(*init)(struct event_base *);
int (*add)(void *, struct event *);
int (*del)(void *, struct event *);
int (*recalc)(struct event_base *, void *, int);
int (*dispatch)(struct event_base *, void *, struct timeval *);
void (*dealloc)(void *);
void (*dealloc)(struct event_base *, void *);
};
#define TIMEOUT_DEFAULT {5, 0}
@ -184,6 +184,7 @@ int event_base_loopexit(struct event_base *, struct timeval *);
void event_set(struct event *, int, short, void (*)(int, short, void *), void *);
int event_once(int, short, void (*)(int, short, void *), void *, struct timeval *);
int event_base_once(struct event_base *, int, short, void (*)(int, short, void *), void *, struct timeval *);
int event_add(struct event *, struct timeval *);
int event_del(struct event *);

View File

@ -81,8 +81,6 @@
#include "log.h"
#include "evsignal.h"
extern volatile sig_atomic_t evsignal_caught;
/*
* Default value for ed_nevents, which is the maximum file descriptor number we
@ -123,7 +121,7 @@ struct evport_data {
struct fd_info *ed_pending[EVENTS_PER_GETN];
};
static void* evport_init (void);
static void* evport_init (struct event_base *);
static int evport_add (void *, struct event *);
static int evport_del (void *, struct event *);
static int evport_recalc (struct event_base *, void *, int);
@ -143,7 +141,7 @@ const struct eventop evportops = {
*/
static void*
evport_init(void)
evport_init(struct event_base *base)
{
struct evport_data *evpd;
/*
@ -172,7 +170,7 @@ evport_init(void)
evpd->ed_nevents = DEFAULT_NFDS;
memset(&evpd->ed_pending, 0, EVENTS_PER_GETN * sizeof(struct fd_info*));
evsignal_init();
evsignal_init(base);
return (evpd);
}
@ -332,7 +330,7 @@ evport_dispatch(struct event_base *base, void *arg, struct timeval *tv)
if ((res = port_getn(epdp->ed_port, pevtlist, EVENTS_PER_GETN,
&nevents, &ts)) == -1) {
if (errno == EINTR) {
evsignal_process();
evsignal_process(base);
return (0);
} else if (errno == ETIME) {
if (nevents == 0)
@ -341,8 +339,8 @@ evport_dispatch(struct event_base *base, void *arg, struct timeval *tv)
perror("port_getn");
return (-1);
}
} else if (evsignal_caught) {
evsignal_process();
} else if (base->sig.evsignal_caught) {
evsignal_process(base);
}
event_debug(("%s: port_getn reports %d events", __func__, nevents));

View File

@ -27,9 +27,18 @@
#ifndef _EVSIGNAL_H_
#define _EVSIGNAL_H_
void evsignal_init(void);
void evsignal_process(void);
struct evsignal_info {
struct event_list signalqueue;
struct event ev_signal;
int ev_signal_pair[2];
int ev_signal_added;
volatile sig_atomic_t evsignal_caught;
sig_atomic_t evsigcaught[NSIG];
};
void evsignal_init(struct event_base *);
void evsignal_process(struct event_base *);
int evsignal_add(struct event *);
int evsignal_del(struct event *);
void evsignal_dealloc(struct event_base *);
#endif /* _EVSIGNAL_H_ */

View File

@ -69,13 +69,13 @@ struct kqop {
int kq;
};
void *kq_init (void);
void *kq_init (struct event_base *);
int kq_add (void *, struct event *);
int kq_del (void *, struct event *);
int kq_recalc (struct event_base *, void *, int);
int kq_dispatch (struct event_base *, void *, struct timeval *);
int kq_insert (struct kqop *, struct kevent *);
void kq_dealloc (void *);
void kq_dealloc (struct event_base *, void *);
const struct eventop kqops = {
"kqueue",
@ -88,7 +88,7 @@ const struct eventop kqops = {
};
void *
kq_init(void)
kq_init(struct event_base *base)
{
int kq;
struct kqop *kqueueop;
@ -398,7 +398,7 @@ kq_del(void *arg, struct event *ev)
}
void
kq_dealloc(void *arg)
kq_dealloc(struct event_base *base, void *arg)
{
struct kqop *kqop = arg;

20
poll.c
View File

@ -54,8 +54,6 @@
#include "evsignal.h"
#include "log.h"
extern volatile sig_atomic_t evsignal_caught;
struct pollop {
int event_count; /* Highest number alloc */
int nfds; /* Size of event_* */
@ -68,12 +66,12 @@ struct pollop {
* "no entry." */
};
void *poll_init (void);
void *poll_init (struct event_base *);
int poll_add (void *, struct event *);
int poll_del (void *, struct event *);
int poll_recalc (struct event_base *, void *, int);
int poll_dispatch (struct event_base *, void *, struct timeval *);
void poll_dealloc (void *);
void poll_dealloc (struct event_base *, void *);
const struct eventop pollops = {
"poll",
@ -86,7 +84,7 @@ const struct eventop pollops = {
};
void *
poll_init(void)
poll_init(struct event_base *base)
{
struct pollop *pollop;
@ -97,7 +95,7 @@ poll_init(void)
if (!(pollop = calloc(1, sizeof(struct pollop))))
return (NULL);
evsignal_init();
evsignal_init(base);
return (pollop);
}
@ -164,10 +162,11 @@ poll_dispatch(struct event_base *base, void *arg, struct timeval *tv)
return (-1);
}
evsignal_process();
evsignal_process(base);
return (0);
} else if (evsignal_caught)
evsignal_process();
} else if (base->sig.evsignal_caught) {
evsignal_process(base);
}
event_debug(("%s: poll reports %d", __func__, res));
@ -370,10 +369,11 @@ poll_del(void *arg, struct event *ev)
}
void
poll_dealloc(void *arg)
poll_dealloc(struct event_base *base, void *arg)
{
struct pollop *pop = arg;
evsignal_dealloc(base);
if (pop->event_set)
free(pop->event_set);
if (pop->event_r_back)

View File

@ -223,7 +223,7 @@ struct rtdata {
int poll_position;
};
void *rtsig_init(void);
void *rtsig_init(struct event_base *);
int rtsig_add(void *, struct event *);
int rtsig_del(void *, struct event *);
int rtsig_recalc(struct event_base *, void *, int);
@ -544,7 +544,7 @@ activate(struct event *ev, int flags)
} while (0)
void *
rtsig_init(void)
rtsig_init(struct event_base *)
{
struct rtsigop *op;
int sockets[2];

View File

@ -57,8 +57,6 @@
#define howmany(x, y) (((x)+((y)-1))/(y))
#endif
extern volatile sig_atomic_t evsignal_caught;
struct selectop {
int event_fds; /* Highest fd in fd set */
int event_fdsz;
@ -70,12 +68,12 @@ struct selectop {
struct event **event_w_by_fd;
};
void *select_init (void);
void *select_init (struct event_base *);
int select_add (void *, struct event *);
int select_del (void *, struct event *);
int select_recalc (struct event_base *, void *, int);
int select_dispatch (struct event_base *, void *, struct timeval *);
void select_dealloc (void *);
void select_dealloc (struct event_base *, void *);
const struct eventop selectops = {
"select",
@ -90,7 +88,7 @@ const struct eventop selectops = {
static int select_resize(struct selectop *sop, int fdsz);
void *
select_init(void)
select_init(struct event_base *base)
{
struct selectop *sop;
@ -103,7 +101,7 @@ select_init(void)
select_resize(sop, howmany(32 + 1, NFDBITS)*sizeof(fd_mask));
evsignal_init();
evsignal_init(base);
return (sop);
}
@ -113,7 +111,7 @@ static void
check_selectop(struct selectop *sop)
{
int i;
for (i=0;i<=sop->event_fds;++i) {
for (i = 0; i <= sop->event_fds; ++i) {
if (FD_ISSET(i, sop->event_readset_in)) {
assert(sop->event_r_by_fd[i]);
assert(sop->event_r_by_fd[i]->ev_events & EV_READ);
@ -174,10 +172,11 @@ select_dispatch(struct event_base *base, void *arg, struct timeval *tv)
return (-1);
}
evsignal_process();
evsignal_process(base);
return (0);
} else if (evsignal_caught)
evsignal_process();
} else if (base->sig.evsignal_caught) {
evsignal_process(base);
}
event_debug(("%s: select reports %d", __func__, res));
@ -348,10 +347,11 @@ select_del(void *arg, struct event *ev)
}
void
select_dealloc(void *arg)
select_dealloc(struct event_base *base, void *arg)
{
struct selectop *sop = arg;
evsignal_dealloc(base);
if (sop->event_readset_in)
free(sop->event_readset_in);
if (sop->event_writeset_in)

View File

@ -31,6 +31,7 @@
#endif
#include <sys/types.h>
#include <sys/tree.h>
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#else
@ -47,19 +48,14 @@
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif
#include <assert.h>
#include "event.h"
#include "event-internal.h"
#include "evsignal.h"
#include "log.h"
extern struct event_list signalqueue;
static sig_atomic_t evsigcaught[NSIG];
volatile sig_atomic_t evsignal_caught = 0;
static struct event ev_signal;
static int ev_signal_pair[2];
static int ev_signal_added;
struct event_base *evsignal_base = NULL;
static void evsignal_handler(int sig);
@ -87,24 +83,27 @@ evsignal_cb(int fd, short what, void *arg)
#endif
void
evsignal_init(void)
evsignal_init(struct event_base *base)
{
/*
* Our signal handler is going to write to one end of the socket
* pair to wake up our event loop. The event loop then scans for
* signals that got delivered.
*/
if (socketpair(AF_UNIX, SOCK_STREAM, 0, ev_signal_pair) == -1)
if (socketpair(AF_UNIX, SOCK_STREAM, 0, base->sig.ev_signal_pair) == -1)
event_err(1, "%s: socketpair", __func__);
FD_CLOSEONEXEC(ev_signal_pair[0]);
FD_CLOSEONEXEC(ev_signal_pair[1]);
FD_CLOSEONEXEC(base->sig.ev_signal_pair[0]);
FD_CLOSEONEXEC(base->sig.ev_signal_pair[1]);
base->sig.evsignal_caught = 0;
memset(&base->sig.evsigcaught, 0, sizeof(sig_atomic_t)*NSIG);
fcntl(ev_signal_pair[0], F_SETFL, O_NONBLOCK);
fcntl(base->sig.ev_signal_pair[0], F_SETFL, O_NONBLOCK);
event_set(&ev_signal, ev_signal_pair[1], EV_READ,
evsignal_cb, &ev_signal);
ev_signal.ev_flags |= EVLIST_INTERNAL;
event_set(&base->sig.ev_signal, base->sig.ev_signal_pair[1], EV_READ,
evsignal_cb, &base->sig.ev_signal);
base->sig.ev_signal.ev_base = base;
base->sig.ev_signal.ev_flags |= EVLIST_INTERNAL;
}
int
@ -112,6 +111,7 @@ evsignal_add(struct event *ev)
{
int evsignal;
struct sigaction sa;
struct event_base *base = ev->ev_base;
if (ev->ev_events & (EV_READ|EV_WRITE))
event_errx(1, "%s: EV_SIGNAL incompatible use", __func__);
@ -121,29 +121,23 @@ evsignal_add(struct event *ev)
sa.sa_handler = evsignal_handler;
sigfillset(&sa.sa_mask);
sa.sa_flags |= SA_RESTART;
/* catch signals if they happen quickly */
evsignal_base = base;
if (sigaction(evsignal, &sa, NULL) == -1)
return (-1);
if (!ev_signal_added) {
ev_signal_added = 1;
event_add(&ev_signal, NULL);
if (!base->sig.ev_signal_added) {
base->sig.ev_signal_added = 1;
event_add(&base->sig.ev_signal, NULL);
}
return (0);
}
/*
* Nothing to be done here.
*/
int
evsignal_del(struct event *ev)
{
int evsignal;
evsignal = EVENT_SIGNAL(ev);
return (sigaction(EVENT_SIGNAL(ev),(struct sigaction *)SIG_DFL, NULL));
}
@ -152,29 +146,50 @@ evsignal_handler(int sig)
{
int save_errno = errno;
evsigcaught[sig]++;
evsignal_caught = 1;
if(evsignal_base == NULL) {
event_warn(
"%s: received signal %s, but have no base configured",
__func__, sig);
return;
}
evsignal_base->sig.evsigcaught[sig]++;
evsignal_base->sig.evsignal_caught = 1;
/* Wake up our notification mechanism */
write(ev_signal_pair[0], "a", 1);
write(evsignal_base->sig.ev_signal_pair[0], "a", 1);
errno = save_errno;
}
void
evsignal_process(void)
evsignal_process(struct event_base *base)
{
struct event *ev;
sig_atomic_t ncalls;
evsignal_caught = 0;
TAILQ_FOREACH(ev, &signalqueue, ev_signal_next) {
ncalls = evsigcaught[EVENT_SIGNAL(ev)];
base->sig.evsignal_caught = 0;
TAILQ_FOREACH(ev, &base->sig.signalqueue, ev_signal_next) {
ncalls = base->sig.evsigcaught[EVENT_SIGNAL(ev)];
if (ncalls) {
if (!(ev->ev_events & EV_PERSIST))
event_del(ev);
event_active(ev, EV_SIGNAL, ncalls);
evsigcaught[EVENT_SIGNAL(ev)] = 0;
base->sig.evsigcaught[EVENT_SIGNAL(ev)] = 0;
}
}
}
void
evsignal_dealloc(struct event_base *base)
{
if(base->sig.ev_signal_added) {
event_del(&base->sig.ev_signal);
base->sig.ev_signal_added = 0;
}
assert(TAILQ_EMPTY(&base->sig.signalqueue));
close(base->sig.ev_signal_pair[0]);
base->sig.ev_signal_pair[0] = -1;
close(base->sig.ev_signal_pair[1]);
base->sig.ev_signal_pair[1] = -1;
}

View File

@ -35,6 +35,7 @@
#endif
#include <sys/types.h>
#include <sys/tree.h>
#include <sys/stat.h>
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
@ -53,6 +54,7 @@
#include <errno.h>
#include "event.h"
#include "event-internal.h"
#include "log.h"
#include "regress.h"
@ -465,6 +467,96 @@ test_immediatesignal(void)
signal_del(&ev);
cleanup_test();
}
void
test_signal_dealloc(void)
{
/* make sure that signal_event is event_del'ed and pipe closed */
struct event ev;
struct event_base *base = event_init();
printf("Signal dealloc: ");
signal_set(&ev, SIGUSR1, signal_cb, &ev);
signal_add(&ev, NULL);
signal_del(&ev);
event_base_free(base);
errno = EINTR;
if (base->sig.ev_signal_added) {
printf("ev_signal not removed (evsignal_dealloc needed) ");
test_ok = 0;
} else if (close(base->sig.ev_signal_pair[0]) != -1 ||
errno != EBADF) {
/* fd must be closed, so second close gives -1, EBADF */
printf("signal pipe still open (evsignal_dealloc needed) ");
test_ok = 0;
} else {
test_ok = 1;
}
cleanup_test();
}
void
test_signal_pipeloss(void)
{
/* make sure that the base1 pipe is closed correctly. */
struct event_base *base1, *base2;
int pipe1;
printf("Signal pipeloss: ");
base1 = event_init();
pipe1 = base1->sig.ev_signal_pair[0];
base2 = event_init();
event_base_free(base2);
event_base_free(base1);
if (close(pipe1) != -1 || errno!=EBADF) {
/* fd must be closed, so second close gives -1, EBADF */
printf("signal pipe not closed. ");
test_ok = 0;
} else {
test_ok = 1;
}
cleanup_test();
}
/*
* make two bases to catch signals, use both of them. this only works
* for event mechanisms that use our signal pipe trick. kqueue handles
* signals internally, and it looks like the first kqueue always gets the
* signal.
*/
void
test_signal_switchbase(void)
{
struct event ev1, ev2;
struct event_base *base1, *base2;
printf("Signal switchbase: ");
base1 = event_init();
base2 = event_init();
signal_set(&ev1, SIGUSR1, signal_cb, &ev1);
signal_set(&ev2, SIGUSR1, signal_cb, &ev2);
if (event_base_set(base1, &ev1) ||
event_base_set(base2, &ev2) ||
event_add(&ev1, NULL) ||
event_add(&ev2, NULL)) {
fprintf(stderr, "%s: cannot set base, add\n", __func__);
exit(1);
}
test_ok = 0;
/* can handle signal before loop is called */
raise(SIGUSR1);
event_base_loop(base2, EVLOOP_NONBLOCK);
event_base_loop(base1, EVLOOP_NONBLOCK);
if (test_ok) {
test_ok = 0;
/* set base1 to handle signals */
event_base_loop(base1, EVLOOP_NONBLOCK);
raise(SIGUSR1);
event_base_loop(base1, EVLOOP_NONBLOCK);
event_base_loop(base2, EVLOOP_NONBLOCK);
}
event_base_free(base1);
event_base_free(base2);
cleanup_test();
}
#endif
void
@ -931,6 +1023,12 @@ main (int argc, char **argv)
test_want_only_once();
#ifndef WIN32
test_signal_dealloc();
test_signal_pipeloss();
test_signal_switchbase();
#endif
evtag_test();
rpc_test();