mirror of
https://github.com/libevent/libevent.git
synced 2025-01-31 09:12:55 +08:00
from trunk: provide event_reinit() to reinitialized an event_base after fork - necessary for epoll/kqueue
svn:r557
This commit is contained in:
parent
5ff1fd7a99
commit
7717cec719
@ -6,6 +6,7 @@ Changes in current version:
|
||||
o better documentation for event_base_loopexit; from Scott Lamb.
|
||||
o Make kqueue have the same behavior as other backends when a signal is caught between event_add() and event_loop(). Previously, it would catch and ignore such signals.
|
||||
o Make kqueue restore signal handlers correctly when event_del() is called.
|
||||
o provide event_reinit() to reintialize an event_base after fork
|
||||
|
||||
|
||||
Changes in 1.4.0-beta:
|
||||
|
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;
|
||||
|
27
event.c
27
event.c
@ -250,6 +250,33 @@ 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);
|
||||
|
||||
if (base->evsel->dealloc != NULL)
|
||||
base->evsel->dealloc(base, base->evbase);
|
||||
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"
|
||||
#include "event-internal.h"
|
||||
|
||||
@ -88,7 +89,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,58 @@ 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);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/* wait for the child to read the data */
|
||||
sleep(1);
|
||||
|
||||
write(pair[0], TEST1, strlen(TEST1)+1);
|
||||
|
||||
if (waitpid(pid, &status, 0) == -1) {
|
||||
fprintf(stderr, "FAILED (fork)\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (WEXITSTATUS(status) != 0) {
|
||||
fprintf(stderr, "FAILED\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* test that the current event loop still works */
|
||||
write(pair[0], TEST1, strlen(TEST1)+1);
|
||||
shutdown(pair[0], SHUT_WR);
|
||||
|
||||
event_dispatch();
|
||||
|
||||
cleanup_test();
|
||||
}
|
||||
|
||||
void
|
||||
test_simplesignal(void)
|
||||
{
|
||||
@ -1199,6 +1252,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