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.
epoll_del,
epoll_recalc,
epoll_dispatch,
- epoll_dealloc
+ epoll_dealloc,
+ 1 /* need reinit */
};
#ifdef HAVE_SETFD
#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;
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)
{
/*
- * 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
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.
*/
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.
#endif
#include "event.h"
+#include "event-internal.h"
#include "log.h"
#define EVLIST_X_KQINKERNEL 0x1000
kq_del,
kq_recalc,
kq_dispatch,
- kq_dealloc
+ kq_dealloc,
+ 1 /* need reinit */
};
void *
#include <sys/queue.h>
#ifndef WIN32
#include <sys/socket.h>
+#include <sys/wait.h>
#include <sys/signal.h>
#include <unistd.h>
#include <netdb.h>
}
#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)
{
dns_suite();
+#ifndef WIN32
+ test_fork();
+#endif
+
test_simpleread();
test_simplewrite();