From b6e64bad555e39013b8a70dff1c1172078d56d1a Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 17 May 2007 02:38:07 +0000 Subject: r22963: fixed the epoll/fork interaction in the epoll and aio backends (This used to be commit aeca07659aa612bee0c4dd6bdbb24c799e912909) --- source4/lib/events/events_aio.c | 42 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) (limited to 'source4/lib/events/events_aio.c') diff --git a/source4/lib/events/events_aio.c b/source4/lib/events/events_aio.c index 204b749332..68109d7265 100644 --- a/source4/lib/events/events_aio.c +++ b/source4/lib/events/events_aio.c @@ -48,6 +48,9 @@ struct aio_event_context { /* a pointer back to the generic event_context */ struct event_context *ev; + /* list of filedescriptor events */ + struct fd_event *fd_events; + /* number of registered fd event handlers */ int num_fd_events; @@ -61,6 +64,7 @@ struct aio_event_context { int epoll_fd; int is_epoll_set; + pid_t pid; }; struct aio_event { @@ -92,6 +96,28 @@ static int aio_ctx_destructor(struct aio_event_context *aio_ev) return 0; } +static void epoll_add_event(struct aio_event_context *aio_ev, struct fd_event *fde); + +/* + reopen the epoll handle when our pid changes + see http://junkcode.samba.org/ftp/unpacked/junkcode/epoll_fork.c for an + demonstration of why this is needed + */ +static void epoll_reopen(struct aio_event_context *aio_ev) +{ + struct fd_event *fde; + + close(aio_ev->epoll_fd); + aio_ev->epoll_fd = epoll_create(64); + if (aio_ev->epoll_fd == -1) { + return; + } + aio_ev->pid = getpid(); + for (fde=aio_ev->fd_events;fde;fde=fde->next) { + epoll_add_event(aio_ev, fde); + } +} + #define EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT (1<<0) #define EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR (1<<1) #define EPOLL_ADDITIONAL_FD_FLAG_GOT_ERROR (1<<2) @@ -104,6 +130,16 @@ static void epoll_add_event(struct aio_event_context *aio_ev, struct fd_event *f struct epoll_event event; if (aio_ev->epoll_fd == -1) return; + /* during an add event we need to check if our pid has changed + and re-open the epoll socket. Note that we don't need to do this + for other epoll changes */ + if (aio_ev->pid != getpid()) { + epoll_reopen(aio_ev); + /* the current event gets added in epoll_reopen(), so + we can return here */ + return; + } + fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR; /* if we don't want events yet, don't add an aio_event */ @@ -127,6 +163,9 @@ static void epoll_add_event(struct aio_event_context *aio_ev, struct fd_event *f static void epoll_del_event(struct aio_event_context *aio_ev, struct fd_event *fde) { struct epoll_event event; + + DLIST_REMOVE(aio_ev->fd_events, fde); + if (aio_ev->epoll_fd == -1) return; fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR; @@ -185,6 +224,7 @@ static void epoll_change_event(struct aio_event_context *aio_ev, struct fd_event /* there's no aio_event attached to the fde */ if (want_read || (want_write && !got_error)) { + DLIST_ADD(aio_ev->fd_events, fde); epoll_add_event(aio_ev, fde); return; } @@ -334,6 +374,7 @@ static int aio_event_context_init(struct event_context *ev) talloc_free(aio_ev); return -1; } + aio_ev->pid = getpid(); talloc_set_destructor(aio_ev, aio_ctx_destructor); @@ -396,6 +437,7 @@ static struct fd_event *aio_event_add_fd(struct event_context *ev, TALLOC_CTX *m aio_ev->num_fd_events++; talloc_set_destructor(fde, aio_event_fd_destructor); + DLIST_ADD(aio_ev->fd_events, fde); epoll_add_event(aio_ev, fde); return fde; -- cgit