mirror of
https://github.com/cuberite/libevent.git
synced 2025-09-12 13:58:58 -04:00
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:
parent
a968da7425
commit
41b7cbc381
@ -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;
|
||||
|
||||
|
20
devpoll.c
20
devpoll.c
@ -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
22
epoll.c
@ -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)
|
||||
|
@ -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;
|
||||
|
||||
|
3
event.3
3
event.3
@ -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
63
event.c
@ -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(¤t_base->event_tv);
|
||||
gettime(&base->event_tv);
|
||||
|
||||
RB_INIT(¤t_base->timetree);
|
||||
TAILQ_INIT(¤t_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);
|
||||
|
5
event.h
5
event.h
@ -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 *);
|
||||
|
14
evport.c
14
evport.c
@ -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));
|
||||
|
13
evsignal.h
13
evsignal.h
@ -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_ */
|
||||
|
8
kqueue.c
8
kqueue.c
@ -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
20
poll.c
@ -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)
|
||||
|
4
rtsig.c
4
rtsig.c
@ -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];
|
||||
|
22
select.c
22
select.c
@ -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)
|
||||
|
85
signal.c
85
signal.c
@ -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;
|
||||
}
|
||||
|
@ -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();
|
||||
|
Loading…
x
Reference in New Issue
Block a user