mirror of
https://github.com/cuberite/libevent.git
synced 2025-09-10 21:10:06 -04:00
provide event_reinit() to reinitialized an event_base after fork - necessary for epoll/kqueue
svn:r539
This commit is contained in:
parent
8c3396b0c6
commit
88897852fc
@ -5,6 +5,7 @@ Changes in current version:
|
||||
o bufferevent_write now uses a const source argument; report from Charles Kerr
|
||||
o improve documentation on event_base_loopexit; patch from Scott Lamb
|
||||
o New function, event_{base_}loopbreak. Like event_loopexit, it makes an event loop stop executing and return. Unlike event_loopexit, it keeps subsequent pending events from getting executed. Patch from Scott Lamb
|
||||
o provide event_reinit() to reintialize an event_base after fork
|
||||
|
||||
Changes in 1.4.0:
|
||||
o allow \r or \n individually to separate HTTP headers instead of the standard "\r\n"; from Charles Kerr.
|
||||
|
3
epoll.c
3
epoll.c
@ -83,7 +83,8 @@ struct eventop epollops = {
|
||||
epoll_del,
|
||||
epoll_recalc,
|
||||
epoll_dispatch,
|
||||
epoll_dealloc
|
||||
epoll_dealloc,
|
||||
1 /* need reinit */
|
||||
};
|
||||
|
||||
#ifdef HAVE_SETFD
|
||||
|
@ -35,6 +35,18 @@ extern "C" {
|
||||
#include "min_heap.h"
|
||||
#include "evsignal.h"
|
||||
|
||||
struct eventop {
|
||||
const char *name;
|
||||
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)(struct event_base *, void *);
|
||||
/* set if we need to reinitialize the event base */
|
||||
int need_reinit;
|
||||
};
|
||||
|
||||
struct event_base {
|
||||
const struct eventop *evsel;
|
||||
void *evbase;
|
||||
|
25
event.c
25
event.c
@ -250,6 +250,31 @@ event_base_free(struct event_base *base)
|
||||
free(base);
|
||||
}
|
||||
|
||||
/* reinitialized the event base after a fork */
|
||||
int
|
||||
event_reinit(struct event_base *base)
|
||||
{
|
||||
const struct eventop *evsel = base->evsel;
|
||||
int res = 0;
|
||||
struct event *ev;
|
||||
|
||||
/* check if this event mechanism requires reinit */
|
||||
if (!evsel->need_reinit)
|
||||
return (0);
|
||||
|
||||
base->evbase = evsel->init(base);
|
||||
if (base->evbase == NULL)
|
||||
event_errx(1, "%s: could not reinitialize event mechanism",
|
||||
__func__);
|
||||
|
||||
TAILQ_FOREACH(ev, &base->eventqueue, ev_next) {
|
||||
if (evsel->add(base, ev) == -1)
|
||||
res = -1;
|
||||
}
|
||||
|
||||
return (res);
|
||||
}
|
||||
|
||||
int
|
||||
event_priority_init(int npriorities)
|
||||
{
|
||||
|
23
event.h
23
event.h
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000-2004 Niels Provos <provos@citi.umich.edu>
|
||||
* Copyright (c) 2000-2007 Niels Provos <provos@citi.umich.edu>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -257,16 +257,6 @@ TAILQ_HEAD (event_list, event);
|
||||
TAILQ_HEAD (evkeyvalq, evkeyval);
|
||||
#endif /* _EVENT_DEFINED_TQENTRY */
|
||||
|
||||
struct eventop {
|
||||
const char *name;
|
||||
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)(struct event_base *, void *);
|
||||
};
|
||||
|
||||
/**
|
||||
Initialize the event API.
|
||||
|
||||
@ -289,6 +279,17 @@ struct event_base *event_base_new(void);
|
||||
*/
|
||||
struct event_base *event_init(void);
|
||||
|
||||
/**
|
||||
Reinitialized the event base after a fork
|
||||
|
||||
Some event mechanisms do not survive across fork. The event base needs
|
||||
to be reinitialized with the event_reinit() function.
|
||||
|
||||
@param base the event base that needs to be re-initialized
|
||||
@return 0 if successful, or -1 if some events could not be re-added.
|
||||
@see event_base_new(), event_init()
|
||||
*/
|
||||
int event_reinit(struct event_base *base);
|
||||
|
||||
/**
|
||||
Loop to process events.
|
||||
|
4
kqueue.c
4
kqueue.c
@ -58,6 +58,7 @@
|
||||
#endif
|
||||
|
||||
#include "event.h"
|
||||
#include "event-internal.h"
|
||||
#include "log.h"
|
||||
|
||||
#define EVLIST_X_KQINKERNEL 0x1000
|
||||
@ -87,7 +88,8 @@ const struct eventop kqops = {
|
||||
kq_del,
|
||||
kq_recalc,
|
||||
kq_dispatch,
|
||||
kq_dealloc
|
||||
kq_dealloc,
|
||||
1 /* need reinit */
|
||||
};
|
||||
|
||||
void *
|
||||
|
@ -42,6 +42,7 @@
|
||||
#include <sys/queue.h>
|
||||
#ifndef WIN32
|
||||
#include <sys/socket.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/signal.h>
|
||||
#include <unistd.h>
|
||||
#include <netdb.h>
|
||||
@ -446,6 +447,47 @@ test_simpletimeout(void)
|
||||
}
|
||||
|
||||
#ifndef WIN32
|
||||
void
|
||||
test_fork(void)
|
||||
{
|
||||
int status;
|
||||
struct event ev;
|
||||
pid_t pid;
|
||||
|
||||
setup_test("After fork: ");
|
||||
|
||||
write(pair[0], TEST1, strlen(TEST1)+1);
|
||||
shutdown(pair[0], SHUT_WR);
|
||||
|
||||
event_set(&ev, pair[1], EV_READ, simple_read_cb, &ev);
|
||||
if (event_add(&ev, NULL) == -1)
|
||||
exit(1);
|
||||
|
||||
if ((pid = fork()) == 0) {
|
||||
/* in the child */
|
||||
extern struct event_base *current_base;
|
||||
if (event_reinit(current_base) == -1) {
|
||||
fprintf(stderr, "FAILED (reinit)\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
event_dispatch();
|
||||
|
||||
exit(test_ok == 0);
|
||||
}
|
||||
|
||||
event_del(&ev);
|
||||
|
||||
if (waitpid(pid, &status, 0) == -1) {
|
||||
fprintf(stderr, "FAILED (fork)\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
test_ok = WEXITSTATUS(status) == 0;
|
||||
|
||||
cleanup_test();
|
||||
}
|
||||
|
||||
void
|
||||
test_simplesignal(void)
|
||||
{
|
||||
@ -1227,6 +1269,10 @@ main (int argc, char **argv)
|
||||
|
||||
dns_suite();
|
||||
|
||||
#ifndef WIN32
|
||||
test_fork();
|
||||
#endif
|
||||
|
||||
test_simpleread();
|
||||
|
||||
test_simplewrite();
|
||||
|
Loading…
x
Reference in New Issue
Block a user