From 1d94210adc6e0bb8a08fbfc1a516a0f958dbf744 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl@samba.org>
Date: Wed, 16 Jan 2013 12:00:00 +0100
Subject: [PATCH 1/2] winbind: Use standard tevent_context_init

This makes winbind use epoll instead of poll
---
 source3/winbindd/winbindd.c       |   38 ++++++++++++++++++++++++++++++++-----
 source3/winbindd/winbindd.h       |    2 --
 source3/winbindd/winbindd_proto.h |    1 +
 3 files changed, 34 insertions(+), 7 deletions(-)

Index: samba-3.6.22/source3/winbindd/winbindd.c
===================================================================
--- samba-3.6.22.orig/source3/winbindd/winbindd.c
+++ samba-3.6.22/source3/winbindd/winbindd.c
@@ -48,14 +48,42 @@ static bool interactive = False;
 
 extern bool override_logfile;
 
+struct tevent_context *winbind_event_context(void)
+{
+	static struct tevent_context *ev = NULL;
+
+	if (ev != NULL) {
+		return ev;
+	}
+
+	/*
+	 * Note we MUST use the NULL context here, not the autofree context,
+	 * to avoid side effects in forked children exiting.
+	 */
+	ev = tevent_context_init(NULL);
+	if (ev == NULL) {
+		smb_panic("Could not init winbindd's messaging context.\n");
+	}
+	return ev;
+}
+
 struct messaging_context *winbind_messaging_context(void)
 {
-	struct messaging_context *msg_ctx = server_messaging_context();
-	if (likely(msg_ctx != NULL)) {
-		return msg_ctx;
+	static struct messaging_context *msg = NULL;
+
+	if (msg != NULL) {
+		return msg;
+	}
+
+	/*
+	 * Note we MUST use the NULL context here, not the autofree context,
+	 * to avoid side effects in forked children exiting.
+	 */
+	msg = messaging_init(NULL, procid_self(), winbind_event_context());
+	if (msg == NULL) {
+		smb_panic("Could not init winbindd's messaging context.\n");
 	}
-	smb_panic("Could not init winbindd's messaging context.\n");
-	return NULL;
+	return msg;
 }
 
 /* Reload configuration */
Index: samba-3.6.22/source3/winbindd/winbindd.h
===================================================================
--- samba-3.6.22.orig/source3/winbindd/winbindd.h
+++ samba-3.6.22/source3/winbindd/winbindd.h
@@ -397,6 +397,4 @@ struct WINBINDD_CCACHE_ENTRY {
 #define WINBINDD_PAM_AUTH_KRB5_RENEW_TIME 2592000 /* one month */
 #define DOM_SEQUENCE_NONE ((uint32)-1)
 
-#define winbind_event_context server_event_context
-
 #endif /* _WINBINDD_H */
Index: samba-3.6.22/source3/winbindd/winbindd_proto.h
===================================================================
--- samba-3.6.22.orig/source3/winbindd/winbindd_proto.h
+++ samba-3.6.22/source3/winbindd/winbindd_proto.h
@@ -34,6 +34,7 @@ bool winbindd_use_cache(void);
 void winbindd_register_handlers(void);
 const char *get_winbind_pipe_dir(void);
 char *get_winbind_priv_pipe_dir(void);
+struct tevent_context *winbind_event_context(void);
 int main(int argc, char **argv, char **envp);
 
 /* The following definitions come from winbindd/winbindd_ads.c  */
Index: samba-3.6.22/source3/winbindd/winbindd_dual.c
===================================================================
--- samba-3.6.22.orig/source3/winbindd/winbindd_dual.c
+++ samba-3.6.22/source3/winbindd/winbindd_dual.c
@@ -1284,6 +1284,66 @@ NTSTATUS winbindd_reinit_after_fork(cons
 	return NT_STATUS_OK;
 }
 
+struct child_handler_state {
+	struct winbindd_child *child;
+	struct winbindd_cli_state *cli_state;
+};
+
+static void child_handler(struct tevent_context *ev, struct tevent_fd *fde,
+			  uint16_t flags, void *private_data)
+{
+	struct child_handler_state *ch_state =
+		(struct child_handler_state *)private_data;
+	struct winbindd_cli_state *state = ch_state->cli_state;
+	struct iovec iov[2];
+	int iov_count;
+	NTSTATUS status;
+
+	if ((flags & TEVENT_FD_READ) == 0) {
+		return;
+	}
+
+	/* fetch a request from the main daemon */
+	status = child_read_request(state);
+
+	if (!NT_STATUS_IS_OK(status)) {
+		/* we lost contact with our parent */
+		_exit(0);
+	}
+
+	DEBUG(4,("child daemon request %d\n", (int)state->request->cmd));
+
+	ZERO_STRUCTP(state->response);
+	state->request->null_term = '\0';
+	state->mem_ctx = talloc_tos();
+	child_process_request(ch_state->child, state);
+
+	DEBUG(4, ("Finished processing child request %d\n",
+		  (int)state->request->cmd));
+
+	SAFE_FREE(state->request->extra_data.data);
+
+	iov[0].iov_base = (void *)state->response;
+	iov[0].iov_len = sizeof(struct winbindd_response);
+	iov_count = 1;
+
+	if (state->response->length > sizeof(struct winbindd_response)) {
+		iov[1].iov_base =
+			(void *)state->response->extra_data.data;
+		iov[1].iov_len = state->response->length-iov[0].iov_len;
+		iov_count = 2;
+	}
+
+	DEBUG(10, ("Writing %d bytes to parent\n",
+		   (int)state->response->length));
+
+	if (write_data_iov(state->sock, iov, iov_count) !=
+	    state->response->length) {
+		DEBUG(0, ("Could not write result\n"));
+		exit(1);
+	}
+}
+
 /*
  * In a child there will be only one domain, reference that here.
  */
@@ -1301,6 +1361,7 @@ static bool fork_domain_child(struct win
 	struct winbindd_request request;
 	struct winbindd_response response;
 	struct winbindd_domain *primary_domain = NULL;
+	struct child_handler_state ch_state;
 	NTSTATUS status;
 	ssize_t nwritten;
 
@@ -1322,6 +1383,9 @@ static bool fork_domain_child(struct win
 	state.request = &request;
 	state.response = &response;
 
+	ch_state.child = child;
+	ch_state.cli_state = &state;
+
 	child->pid = sys_fork();
 
 	if (child->pid == -1) {
@@ -1464,22 +1528,14 @@ static bool fork_domain_child(struct win
 		}
 	}
 
-	while (1) {
+	if (tevent_add_fd(winbind_event_context(), NULL, state.sock,
+			  TEVENT_FD_READ, child_handler, &ch_state) == NULL) {
+		DEBUG(1, ("tevent_add_fd failed\n"));
+		exit(1);
+	}
 
-		int ret;
-		struct pollfd *pfds;
-		int num_pfds;
-		int timeout;
-		struct timeval t;
-		struct timeval *tp;
+	while (1) {
 		TALLOC_CTX *frame = talloc_stackframe();
-		struct iovec iov[2];
-		int iov_count;
-
-		if (run_events_poll(winbind_event_context(), 0, NULL, 0)) {
-			TALLOC_FREE(frame);
-			continue;
-		}
 
 		if (child->domain && child->domain->startup &&
 				(time_mono(NULL) > child->domain->startup_time + 30)) {
@@ -1489,99 +1545,12 @@ static bool fork_domain_child(struct win
 			child->domain->startup = False;
 		}
 
-		pfds = TALLOC_ZERO_P(talloc_tos(), struct pollfd);
-		if (pfds == NULL) {
-			DEBUG(1, ("talloc failed\n"));
-			_exit(1);
-		}
-
-		pfds->fd = state.sock;
-		pfds->events = POLLIN|POLLHUP;
-		num_pfds = 1;
-
-		timeout = INT_MAX;
-
-		if (!event_add_to_poll_args(
-			    winbind_event_context(), talloc_tos(),
-			    &pfds, &num_pfds, &timeout)) {
-			DEBUG(1, ("event_add_to_poll_args failed\n"));
-			_exit(1);
-		}
-		tp = get_timed_events_timeout(winbind_event_context(), &t);
-		if (tp) {
-			DEBUG(11,("select will use timeout of %u.%u seconds\n",
-				(unsigned int)tp->tv_sec, (unsigned int)tp->tv_usec ));
-		}
-
-		ret = sys_poll(pfds, num_pfds, timeout);
-
-		if (run_events_poll(winbind_event_context(), ret,
-				    pfds, num_pfds)) {
-			/* We got a signal - continue. */
-			TALLOC_FREE(frame);
-			continue;
-		}
-
-		TALLOC_FREE(pfds);
-
-		if (ret == 0) {
-			DEBUG(11,("nothing is ready yet, continue\n"));
-			TALLOC_FREE(frame);
-			continue;
-		}
-
-		if (ret == -1 && errno == EINTR) {
-			/* We got a signal - continue. */
-			TALLOC_FREE(frame);
-			continue;
-		}
-
-		if (ret == -1 && errno != EINTR) {
-			DEBUG(0,("poll error occured\n"));
-			TALLOC_FREE(frame);
-			perror("poll");
+		if (tevent_loop_once(winbind_event_context()) != 0) {
+			DEBUG(1, ("tevent_loop_once failed: %s\n",
+				  strerror(errno)));
 			_exit(1);
 		}
 
-		/* fetch a request from the main daemon */
-		status = child_read_request(&state);
-
-		if (!NT_STATUS_IS_OK(status)) {
-			/* we lost contact with our parent */
-			_exit(0);
-		}
-
-		DEBUG(4,("child daemon request %d\n", (int)state.request->cmd));
-
-		ZERO_STRUCTP(state.response);
-		state.request->null_term = '\0';
-		state.mem_ctx = frame;
-		child_process_request(child, &state);
-
-		DEBUG(4, ("Finished processing child request %d\n",
-			  (int)state.request->cmd));
-
-		SAFE_FREE(state.request->extra_data.data);
-
-		iov[0].iov_base = (void *)state.response;
-		iov[0].iov_len = sizeof(struct winbindd_response);
-		iov_count = 1;
-
-		if (state.response->length > sizeof(struct winbindd_response)) {
-			iov[1].iov_base =
-				(void *)state.response->extra_data.data;
-			iov[1].iov_len = state.response->length-iov[0].iov_len;
-			iov_count = 2;
-		}
-
-		DEBUG(10, ("Writing %d bytes to parent\n",
-			   (int)state.response->length));
-
-		if (write_data_iov(state.sock, iov, iov_count) !=
-		    state.response->length) {
-			DEBUG(0, ("Could not write result\n"));
-			exit(1);
-		}
 		TALLOC_FREE(frame);
 	}
 }
