svn commit: samba r22963 - in branches/SAMBA_4_0/source/lib/events:
.
tridge at samba.org
tridge at samba.org
Thu May 17 02:38:08 GMT 2007
Author: tridge
Date: 2007-05-17 02:38:07 +0000 (Thu, 17 May 2007)
New Revision: 22963
WebSVN: http://websvn.samba.org/cgi-bin/viewcvs.cgi?view=rev&root=samba&rev=22963
Log:
fixed the epoll/fork interaction in the epoll and aio backends
Modified:
branches/SAMBA_4_0/source/lib/events/events_aio.c
branches/SAMBA_4_0/source/lib/events/events_epoll.c
Changeset:
Modified: branches/SAMBA_4_0/source/lib/events/events_aio.c
===================================================================
--- branches/SAMBA_4_0/source/lib/events/events_aio.c 2007-05-17 02:22:29 UTC (rev 22962)
+++ branches/SAMBA_4_0/source/lib/events/events_aio.c 2007-05-17 02:38:07 UTC (rev 22963)
@@ -48,6 +48,9 @@
/* 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 @@
int epoll_fd;
int is_epoll_set;
+ pid_t pid;
};
struct aio_event {
@@ -92,6 +96,28 @@
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 @@
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_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 @@
/* 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 @@
talloc_free(aio_ev);
return -1;
}
+ aio_ev->pid = getpid();
talloc_set_destructor(aio_ev, aio_ctx_destructor);
@@ -396,6 +437,7 @@
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;
Modified: branches/SAMBA_4_0/source/lib/events/events_epoll.c
===================================================================
--- branches/SAMBA_4_0/source/lib/events/events_epoll.c 2007-05-17 02:22:29 UTC (rev 22962)
+++ branches/SAMBA_4_0/source/lib/events/events_epoll.c 2007-05-17 02:38:07 UTC (rev 22963)
@@ -32,6 +32,9 @@
/* 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;
@@ -45,6 +48,8 @@
/* when using epoll this is the handle from epoll_create */
int epoll_fd;
+
+ pid_t pid;
};
/*
@@ -86,9 +91,32 @@
static void epoll_init_ctx(struct epoll_event_context *epoll_ev)
{
epoll_ev->epoll_fd = epoll_create(64);
+ epoll_ev->pid = getpid();
talloc_set_destructor(epoll_ev, epoll_ctx_destructor);
}
+static void epoll_add_event(struct epoll_event_context *epoll_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 epoll_event_context *epoll_ev)
+{
+ struct fd_event *fde;
+
+ close(epoll_ev->epoll_fd);
+ epoll_ev->epoll_fd = epoll_create(64);
+ if (epoll_ev->epoll_fd == -1) {
+ return;
+ }
+ epoll_ev->pid = getpid();
+ for (fde=epoll_ev->fd_events;fde;fde=fde->next) {
+ epoll_add_event(epoll_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)
@@ -99,8 +127,19 @@
static void epoll_add_event(struct epoll_event_context *epoll_ev, struct fd_event *fde)
{
struct epoll_event event;
+
if (epoll_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 (epoll_ev->pid != getpid()) {
+ epoll_reopen(epoll_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 epoll_event */
@@ -126,6 +165,9 @@
static void epoll_del_event(struct epoll_event_context *epoll_ev, struct fd_event *fde)
{
struct epoll_event event;
+
+ DLIST_REMOVE(epoll_ev->fd_events, fde);
+
if (epoll_ev->epoll_fd == -1) return;
fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR;
@@ -193,6 +235,7 @@
/* there's no epoll_event attached to the fde */
if (want_read || (want_write && !got_error)) {
+ DLIST_ADD(epoll_ev->fd_events, fde);
epoll_add_event(epoll_ev, fde);
return;
}
@@ -343,6 +386,7 @@
epoll_ev->num_fd_events++;
talloc_set_destructor(fde, epoll_event_fd_destructor);
+ DLIST_ADD(epoll_ev->fd_events, fde);
epoll_add_event(epoll_ev, fde);
return fde;
More information about the samba-cvs
mailing list