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