[SCM] Samba Shared Repository - branch master updated

Andrew Tridgell tridge at samba.org
Tue Mar 9 03:50:59 MST 2010


The branch, master has been updated
       via  ec53a0c... s4:dsdb/dns: change callers of samba_runcmd()
       via  6ea3393... lib/util: change samba_runcmd() to use tevent_req _send/_recv
      from  56b13ee... Revert "Fix bug #7067 - Linux asynchronous IO (aio) can cause smbd to fail to respond to a read or write."

http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit ec53a0ca5a568627df8dac91ec2c736b0d106829
Author: Stefan Metzmacher <metze at samba.org>
Date:   Thu Feb 25 16:01:15 2010 +0100

    s4:dsdb/dns: change callers of samba_runcmd()
    
    metze

commit 6ea339379890fa1f99e802cac4f705b96ffcff8d
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed Feb 24 12:43:45 2010 +0100

    lib/util: change samba_runcmd() to use tevent_req _send/_recv
    
    metze

-----------------------------------------------------------------------

Summary of changes:
 lib/util/util.h               |   15 +-
 lib/util/util_runcmd.c        |  319 +++++++++++++++++++++++------------------
 source4/dsdb/dns/dns_update.c |  104 +++++++++-----
 3 files changed, 256 insertions(+), 182 deletions(-)


Changeset truncated at 500 lines:

diff --git a/lib/util/util.h b/lib/util/util.h
index 264396e..e1160d5 100644
--- a/lib/util/util.h
+++ b/lib/util/util.h
@@ -890,12 +890,13 @@ bool add_gid_to_array_unique(TALLOC_CTX *mem_ctx, gid_t gid,
   with the return code from the command
  */
 struct tevent_context;
-struct composite_context *samba_runcmd(struct tevent_context *ev,
-				       TALLOC_CTX *mem_ctx,
-				       struct timeval timeout,
-				       int stdout_log_level,
-				       int stderr_log_level,
-				       const char **argv0, ...);
-
+struct tevent_req;
+struct tevent_req *samba_runcmd_send(TALLOC_CTX *mem_ctx,
+				     struct tevent_context *ev,
+				     struct timeval endtime,
+				     int stdout_log_level,
+				     int stderr_log_level,
+				     const char * const *argv0, ...);
+int samba_runcmd_recv(struct tevent_req *req, int *perrno);
 
 #endif /* _SAMBA_UTIL_H_ */
diff --git a/lib/util/util_runcmd.c b/lib/util/util_runcmd.c
index dea3ff9..ef897d4 100644
--- a/lib/util/util_runcmd.c
+++ b/lib/util/util_runcmd.c
@@ -28,9 +28,9 @@
 #include "includes.h"
 #include "system/filesys.h"
 #include "lib/tevent/tevent.h"
-#include "libcli/composite/composite.h"
+#include "lib/util/tevent_unix.h"
 
-struct samba_runcmd {
+struct samba_runcmd_state {
 	int stdout_log_level;
 	int stderr_log_level;
 	struct tevent_fd *fde_stdout;
@@ -42,106 +42,20 @@ struct samba_runcmd {
 	uint16_t buf_used;
 };
 
-/*
-  called when a command times out
- */
-static void runcmd_timeout(struct tevent_context *ev,
-			   struct tevent_timer *te,
-			   struct timeval current_time,
-			   void *private_data)
+static int samba_runcmd_state_destructor(struct samba_runcmd_state *state)
 {
-	struct composite_context *c = talloc_get_type_abort(private_data, struct composite_context);
-	struct samba_runcmd *r = talloc_get_type_abort(c->private_data, struct samba_runcmd);
-	kill(r->pid, SIGKILL);
-	waitpid(r->pid, NULL, 0);
-	talloc_free(r->fde_stderr);
-	talloc_free(r->fde_stdout);
-	composite_error(c, NT_STATUS_IO_TIMEOUT);
-}
-
-/*
-  handle stdout/stderr from the child
- */
-static void runcmd_io_handler(struct tevent_context *ev,
-			      struct tevent_fd *fde,
-			      uint16_t flags,
-			      void *private_data)
-{
-	struct composite_context *c = talloc_get_type_abort(private_data, struct composite_context);
-	struct samba_runcmd *r = talloc_get_type_abort(c->private_data, struct samba_runcmd);
-	int level;
-	char *p;
-	int n, fd;
-
-	if (fde == r->fde_stdout) {
-		level = r->stdout_log_level;
-		fd = r->fd_stdout;
-	} else {
-		level = r->stderr_log_level;
-		fd = r->fd_stderr;
-	}
-
-	if (!(flags & TEVENT_FD_READ)) {
-		return;
-	}
-
-	n = read(fd, &r->buf[r->buf_used],
-		 sizeof(r->buf) - r->buf_used);
-	if (n > 0) {
-		r->buf_used += n;
-	} else if (n == 0) {
-		if (fde == r->fde_stdout) {
-			talloc_free(fde);
-			r->fde_stdout = NULL;
-		}
-		if (fde == r->fde_stderr) {
-			talloc_free(fde);
-			r->fde_stderr = NULL;
-		}
-		if (r->fde_stdout == NULL &&
-		    r->fde_stderr == NULL) {
-			int status;
-			/* the child has closed both stdout and
-			 * stderr, assume its dead */
-			pid_t pid = waitpid(r->pid, &status, 0);
-			if (pid != r->pid) {
-				DEBUG(0,("Error in waitpid() for child %s\n", r->arg0));
-				composite_error(c, map_nt_error_from_unix(errno));
-				return;
-			}
-			status = WEXITSTATUS(status);
-			DEBUG(3,("Child %s exited with status %d\n", r->arg0, status));
-			if (status == 0) {
-				composite_done(c);
-			} else {
-				composite_error(c, map_nt_error_from_unix(status));
-			}
-			return;
-		}
-		return;
-	}
-
-	while (r->buf_used > 0 &&
-	       (p = memchr(r->buf, '\n', r->buf_used)) != NULL) {
-		int n1 = (p - r->buf)+1;
-		int n2 = n1 - 1;
-		/* swallow \r from child processes */
-		if (n2 > 0 && r->buf[n2-1] == '\r') {
-			n2--;
-		}
-		DEBUG(level,("%s: %*.*s\n", r->arg0, n2, n2, r->buf));
-		memmove(r->buf, p+1, sizeof(r->buf) - n1);
-		r->buf_used -= n1;
-	}
-
-	/* the buffer could have completely filled - unfortunately we have
-	   no choice but to dump it out straight away */
-	if (r->buf_used == sizeof(r->buf)) {
-		DEBUG(level,("%s: %*.*s\n", r->arg0, r->buf_used, r->buf_used, r->buf));
-		r->buf_used = 0;
+	if (state->pid > 0) {
+		kill(state->pid, SIGKILL);
+		waitpid(state->pid, NULL, 0);
+		state->pid = -1;
 	}
+	return 0;
 }
 
+static void samba_runcmd_io_handler(struct tevent_context *ev,
+				    struct tevent_fd *fde,
+				    uint16_t flags,
+				    void *private_data);
 
 /*
   run a command as a child process, with a timeout.
@@ -149,71 +63,94 @@ static void runcmd_io_handler(struct tevent_context *ev,
   any stdout/stderr from the child will appear in the Samba logs with
   the specified log levels
  */
-struct composite_context *samba_runcmd(struct tevent_context *ev,
-				       TALLOC_CTX *mem_ctx,
-				       struct timeval timeout,
-				       int stdout_log_level,
-				       int stderr_log_level,
-				       const char **argv0, ...)
+struct tevent_req *samba_runcmd_send(TALLOC_CTX *mem_ctx,
+				     struct tevent_context *ev,
+				     struct timeval endtime,
+				     int stdout_log_level,
+				     int stderr_log_level,
+				     const char * const *argv0, ...)
 {
-	struct samba_runcmd *r;
+	struct tevent_req *req;
+	struct samba_runcmd_state *state;
 	int p1[2], p2[2];
 	char **argv;
 	int ret;
 	va_list ap;
-	struct composite_context *c;
-
-	c = composite_create(mem_ctx, ev);
-	if (c == NULL) return NULL;
 
-	r = talloc_zero(c, struct samba_runcmd);
-	if (composite_nomem(r, c)) return c;
-
-	c->private_data = r;
+	req = tevent_req_create(mem_ctx, &state,
+				struct samba_runcmd_state);
+	if (req == NULL) {
+		return NULL;
+	}
 
-	r->stdout_log_level = stdout_log_level;
-	r->stderr_log_level = stderr_log_level;
+	state->stdout_log_level = stdout_log_level;
+	state->stderr_log_level = stderr_log_level;
 
-	r->arg0 = talloc_strdup(r, argv0[0]);
-	if (composite_nomem(r->arg0, c)) return c;
+	state->arg0 = talloc_strdup(state, argv0[0]);
+	if (tevent_req_nomem(state->arg0, req)) {
+		return tevent_req_post(req, ev);
+	}
 
 	if (pipe(p1) != 0) {
-		composite_error(c, map_nt_error_from_unix(errno));
-		return c;
+		tevent_req_error(req, errno);
+		return tevent_req_post(req, ev);
 	}
 	if (pipe(p2) != 0) {
-		composite_error(c, map_nt_error_from_unix(errno));
 		close(p1[0]);
 		close(p1[1]);
-		return c;
+		tevent_req_error(req, errno);
+		return tevent_req_post(req, ev);
 	}
 
-	r->pid = fork();
-	if (r->pid == (pid_t)-1) {
-		composite_error(c, map_nt_error_from_unix(errno));
+	state->pid = fork();
+	if (state->pid == (pid_t)-1) {
 		close(p1[0]);
 		close(p1[1]);
 		close(p2[0]);
 		close(p2[1]);
-		return c;
+		tevent_req_error(req, errno);
+		return tevent_req_post(req, ev);
 	}
 
-	if (r->pid != 0) {
+	if (state->pid != 0) {
 		/* the parent */
 		close(p1[1]);
 		close(p2[1]);
-		r->fd_stdout = p1[0];
-		r->fd_stderr = p2[0];
-		set_blocking(r->fd_stdout, false);
-		set_blocking(r->fd_stderr, false);
-		r->fde_stdout = tevent_add_fd(ev, r, r->fd_stdout, TEVENT_FD_READ, runcmd_io_handler, c);
-		tevent_fd_set_auto_close(r->fde_stdout);
-		r->fde_stderr = tevent_add_fd(ev, r, r->fd_stderr, TEVENT_FD_READ, runcmd_io_handler, c);
-		tevent_fd_set_auto_close(r->fde_stderr);
-		if (!timeval_is_zero(&timeout)) {
-			tevent_add_timer(ev, r, timeout, runcmd_timeout, c);
+		state->fd_stdout = p1[0];
+		state->fd_stderr = p2[0];
+		set_blocking(state->fd_stdout, false);
+		set_blocking(state->fd_stderr, false);
+
+		talloc_set_destructor(state, samba_runcmd_state_destructor);
+
+		state->fde_stdout = tevent_add_fd(ev, state,
+						  state->fd_stdout,
+						  TEVENT_FD_READ,
+						  samba_runcmd_io_handler,
+						  req);
+		if (tevent_req_nomem(state->fde_stdout, req)) {
+			close(p1[0]);
+			close(p2[0]);
+			return tevent_req_post(req, ev);
+		}
+		tevent_fd_set_auto_close(state->fde_stdout);
+
+		state->fde_stderr = tevent_add_fd(ev, state,
+						  state->fd_stderr,
+						  TEVENT_FD_READ,
+						  samba_runcmd_io_handler,
+						  req);
+		if (tevent_req_nomem(state->fde_stdout, req)) {
+			close(p2[0]);
+			return tevent_req_post(req, ev);
+		}
+		tevent_fd_set_auto_close(state->fde_stderr);
+
+		if (!timeval_is_zero(&endtime)) {
+			tevent_req_set_endtime(req, ev, endtime);
 		}
-		return c;
+
+		return req;
 	}
 
 	/* the child */
@@ -228,7 +165,7 @@ struct composite_context *samba_runcmd(struct tevent_context *ev,
 	dup2(p1[1], 1);
 	dup2(p2[1], 2);
 
-	argv = str_list_copy(r, argv0);
+	argv = str_list_copy(state, discard_const_p(const char *, argv0));
 	if (!argv) {
 		fprintf(stderr, "Out of memory in child\n");
 		_exit(255);
@@ -246,8 +183,112 @@ struct composite_context *samba_runcmd(struct tevent_context *ev,
 	}
 	va_end(ap);
 
-	ret = execv(r->arg0, argv);
+	ret = execv(state->arg0, argv);
 	fprintf(stderr, "Failed to exec child - %s\n", strerror(errno));
 	_exit(255);
 	return NULL;
 }
+
+/*
+  handle stdout/stderr from the child
+ */
+static void samba_runcmd_io_handler(struct tevent_context *ev,
+				    struct tevent_fd *fde,
+				    uint16_t flags,
+				    void *private_data)
+{
+	struct tevent_req *req = talloc_get_type_abort(private_data,
+				 struct tevent_req);
+	struct samba_runcmd_state *state = tevent_req_data(req,
+					   struct samba_runcmd_state);
+	int level;
+	char *p;
+	int n, fd;
+
+	if (fde == state->fde_stdout) {
+		level = state->stdout_log_level;
+		fd = state->fd_stdout;
+	} else {
+		level = state->stderr_log_level;
+		fd = state->fd_stderr;
+	}
+
+	if (!(flags & TEVENT_FD_READ)) {
+		return;
+	}
+
+	n = read(fd, &state->buf[state->buf_used],
+		 sizeof(state->buf) - state->buf_used);
+	if (n > 0) {
+		state->buf_used += n;
+	} else if (n == 0) {
+		if (fde == state->fde_stdout) {
+			talloc_free(fde);
+			state->fde_stdout = NULL;
+		}
+		if (fde == state->fde_stderr) {
+			talloc_free(fde);
+			state->fde_stderr = NULL;
+		}
+		if (state->fde_stdout == NULL &&
+		    state->fde_stderr == NULL) {
+			int status;
+			/* the child has closed both stdout and
+			 * stderr, assume its dead */
+			pid_t pid = waitpid(state->pid, &status, 0);
+			if (pid != state->pid) {
+				DEBUG(0,("Error in waitpid() for child %s - %s \n",
+					 state->arg0, strerror(errno)));
+				if (errno == 0) {
+					errno = ECHILD;
+				}
+				tevent_req_error(req, errno);
+				return;
+			}
+			status = WEXITSTATUS(status);
+			DEBUG(3,("Child %s exited with status %d - %s\n",
+				 state->arg0, status, strerror(status)));
+			if (status != 0) {
+				tevent_req_error(req, status);
+				return;
+			}
+
+			tevent_req_done(req);
+			return;
+		}
+		return;
+	}
+
+	while (state->buf_used > 0 &&
+	       (p = (char *)memchr(state->buf, '\n', state->buf_used)) != NULL) {
+		int n1 = (p - state->buf)+1;
+		int n2 = n1 - 1;
+		/* swallow \r from child processes */
+		if (n2 > 0 && state->buf[n2-1] == '\r') {
+			n2--;
+		}
+		DEBUG(level,("%s: %*.*s\n", state->arg0, n2, n2, state->buf));
+		memmove(state->buf, p+1, sizeof(state->buf) - n1);
+		state->buf_used -= n1;
+	}
+
+	/* the buffer could have completely filled - unfortunately we have
+	   no choice but to dump it out straight away */
+	if (state->buf_used == sizeof(state->buf)) {
+		DEBUG(level,("%s: %*.*s\n",
+			     state->arg0, state->buf_used,
+			     state->buf_used, state->buf));
+		state->buf_used = 0;
+	}
+}
+
+int samba_runcmd_recv(struct tevent_req *req, int *perrno)
+{
+	if (tevent_req_is_unix_error(req, perrno)) {
+		tevent_req_received(req);
+		return -1;
+	}
+
+	tevent_req_received(req);
+	return 0;
+}
diff --git a/source4/dsdb/dns/dns_update.c b/source4/dsdb/dns/dns_update.c
index 4fefd65..4e6ee83 100644
--- a/source4/dsdb/dns/dns_update.c
+++ b/source4/dsdb/dns/dns_update.c
@@ -46,7 +46,7 @@ struct dnsupdate_service {
 	struct {
 		uint32_t interval;
 		struct tevent_timer *te;
-		struct composite_context *c;
+		struct tevent_req *subreq;
 		NTSTATUS status;
 	} confupdate;
 
@@ -54,7 +54,7 @@ struct dnsupdate_service {
 	struct {
 		uint32_t interval;
 		struct tevent_timer *te;
-		struct composite_context *c;
+		struct tevent_req *subreq;
 		NTSTATUS status;
 	} nameupdate;
 };
@@ -62,13 +62,23 @@ struct dnsupdate_service {
 /*
   called when rndc reload has finished
  */
-static void dnsupdate_rndc_done(struct composite_context *c)
+static void dnsupdate_rndc_done(struct tevent_req *subreq)
 {
-	struct dnsupdate_service *service = talloc_get_type_abort(c->async.private_data,
-								  struct dnsupdate_service);
-	service->confupdate.status = composite_wait(c);
-	talloc_free(c);
-	service->confupdate.c = NULL;
+	struct dnsupdate_service *service = tevent_req_callback_data(subreq,
+					    struct dnsupdate_service);
+	int ret;
+	int sys_errno;
+
+	service->confupdate.subreq = NULL;
+
+	ret = samba_runcmd_recv(subreq, &sys_errno);
+	TALLOC_FREE(subreq);
+	if (ret != 0) {
+		service->confupdate.status = map_nt_error_from_unix(sys_errno);
+	} else {
+		service->confupdate.status = NT_STATUS_OK;
+	}
+
 	if (!NT_STATUS_IS_OK(service->confupdate.status)) {
 		DEBUG(0,(__location__ ": Failed rndc update - %s\n",
 			 nt_errstr(service->confupdate.status)));
@@ -90,6 +100,10 @@ static void dnsupdate_rebuild(struct dnsupdate_service *service)
 	const char *attrs[] = { "sAMAccountName", NULL };
 	const char *realm = lp_realm(service->task->lp_ctx);
 	TALLOC_CTX *tmp_ctx = talloc_new(service);
+	const char * const *rndc_command = lp_rndc_command(service->task->lp_ctx);
+
+	/* abort any pending script run */
+	TALLOC_FREE(service->confupdate.subreq);
 
 	ret = ldb_search(service->samdb, tmp_ctx, &res, NULL, LDB_SCOPE_SUBTREE,
 			 attrs, "(&(primaryGroupID=%u)(objectClass=computer))",
@@ -136,10 +150,6 @@ static void dnsupdate_rebuild(struct dnsupdate_service *service)
 	dprintf(fd, "};\n");
 	close(fd);
 
-	if (service->confupdate.c != NULL) {
-		talloc_free(service->confupdate.c);
-		service->confupdate.c = NULL;
-	}
 
 	if (NT_STATUS_IS_OK(service->confupdate.status) &&
 	    file_compare(tmp_path, path) == true) {
@@ -156,13 +166,20 @@ static void dnsupdate_rebuild(struct dnsupdate_service *service)
 	}
 
 	DEBUG(2,("Loading new DNS update grant rules\n"));
-	service->confupdate.c = samba_runcmd(service->task->event_ctx, service,
-					     timeval_current_ofs(10, 0),
-					     2, 0,
-					     lp_rndc_command(service->task->lp_ctx),
-					     "reload", NULL);
-	service->confupdate.c->async.fn = dnsupdate_rndc_done;
-	service->confupdate.c->async.private_data = service;


-- 
Samba Shared Repository


More information about the samba-cvs mailing list