svn commit: samba r22959 - in branches/SAMBA_4_0/source/lib/events: .

tridge at samba.org tridge at samba.org
Thu May 17 02:18:30 GMT 2007


Author: tridge
Date: 2007-05-17 02:18:29 +0000 (Thu, 17 May 2007)
New Revision: 22959

WebSVN: http://websvn.samba.org/cgi-bin/viewcvs.cgi?view=rev&root=samba&rev=22959

Log:

cope with a rather interesting interaction between epoll() and
fork(). See
http://junkcode.samba.org/ftp/unpacked/junkcode/epoll_fork.c for why
this is needed

Modified:
   branches/SAMBA_4_0/source/lib/events/events_standard.c


Changeset:
Modified: branches/SAMBA_4_0/source/lib/events/events_standard.c
===================================================================
--- branches/SAMBA_4_0/source/lib/events/events_standard.c	2007-05-17 01:17:43 UTC (rev 22958)
+++ branches/SAMBA_4_0/source/lib/events/events_standard.c	2007-05-17 02:18:29 UTC (rev 22959)
@@ -58,6 +58,9 @@
 
 	/* when using epoll this is the handle from epoll_create */
 	int epoll_fd;
+
+	/* our pid at the time the epoll_fd was created */
+	pid_t pid;
 };
 
 /* use epoll if it is available */
@@ -68,7 +71,9 @@
 */
 static void epoll_fallback_to_select(struct std_event_context *std_ev, const char *reason)
 {
+	const char *cmd = talloc_asprintf(std_ev, "xterm -e gdb --pid %u", getpid());
 	DEBUG(0,("%s (%s) - falling back to select()\n", reason, strerror(errno)));
+	system(cmd);
 	close(std_ev->epoll_fd);
 	std_ev->epoll_fd = -1;
 	talloc_set_destructor(std_ev, NULL);
@@ -90,7 +95,9 @@
 */
 static int epoll_ctx_destructor(struct std_event_context *std_ev)
 {
-	close(std_ev->epoll_fd);
+	if (std_ev->epoll_fd != -1) {
+		close(std_ev->epoll_fd);
+	}
 	std_ev->epoll_fd = -1;
 	return 0;
 }
@@ -101,9 +108,32 @@
 static void epoll_init_ctx(struct std_event_context *std_ev)
 {
 	std_ev->epoll_fd = epoll_create(64);
+	std_ev->pid = getpid();
 	talloc_set_destructor(std_ev, epoll_ctx_destructor);
 }
 
+static void epoll_add_event(struct std_event_context *std_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 std_event_context *std_ev)
+{
+	struct fd_event *fde;
+
+	close(std_ev->epoll_fd);
+	std_ev->epoll_fd = epoll_create(64);
+	if (std_ev->epoll_fd == -1) {
+		return;
+	}
+	std_ev->pid = getpid();
+	for (fde=std_ev->fd_events;fde;fde=fde->next) {
+		epoll_add_event(std_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)
@@ -116,6 +146,16 @@
 	struct epoll_event event;
 	if (std_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 (std_ev->pid != getpid()) {
+		epoll_reopen(std_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 */



More information about the samba-cvs mailing list