[SCM] Samba Shared Repository - branch master updated

Amitay Isaacs amitay at samba.org
Tue Nov 7 06:52:03 UTC 2017


The branch, master has been updated
       via  5c354e1 ctdb-tests: Add sock_daemon test for stale socket handling
       via  ad8d720 ctdb-common: Fix stale socket removal
       via  4b652c1 ctdb-scripts: Don't bother checking PID file when starting ctdbd
       via  f025f5c ctdb-tests: Have fake daemon log when it parses public IPs
       via  28d6356 ctdb-common: Ensure unused bytes in union are initialised
      from  44c018b s4: torture: Add smb2 FIND_and_set_DOC test case.

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


- Log -----------------------------------------------------------------
commit 5c354e10ace279c45f773483dffe84617d879c8e
Author: Martin Schwenke <martin at meltin.net>
Date:   Fri Nov 3 16:24:46 2017 +1100

    ctdb-tests: Add sock_daemon test for stale socket handling
    
    Signed-off-by: Martin Schwenke <martin at meltin.net>
    Reviewed-by: Amitay Isaacs <amitay at gmail.com>
    
    Autobuild-User(master): Amitay Isaacs <amitay at samba.org>
    Autobuild-Date(master): Tue Nov  7 07:51:02 CET 2017 on sn-devel-144

commit ad8d72091e2e8769c1073bccece699e4da412f57
Author: Amitay Isaacs <amitay at gmail.com>
Date:   Fri Nov 3 16:00:04 2017 +1100

    ctdb-common: Fix stale socket removal
    
    Sockets need to be created from sock_daemon_run_send().  This means
    that stale socket removal can depend on the PID file context being
    initialised.
    
    Also fix associated test.
    
    Signed-off-by: Amitay Isaacs <amitay at gmail.com>
    Reviewed-by: Martin Schwenke <martin at meltin.net>

commit 4b652c1527afe7eff4075c95946abfa114d74015
Author: Martin Schwenke <martin at meltin.net>
Date:   Mon Oct 23 11:50:51 2017 +1100

    ctdb-scripts: Don't bother checking PID file when starting ctdbd
    
    This is an optimisation that can cause incorrect results.  If ctdbd
    was killed and there is a stale PID file then this will often cause
    "CTDB exited during initialisation".  The wrapper reads the old PID
    from the PID file, finds the PID gone, complains and exits.
    
    It is better to drop this code and finally get this right.  If ctdbd
    does exit early then it will take CTDB_STARTUP_TIMEOUT (default 10)
    seconds before the wrapper fails.  That's not too bad...
    
    Signed-off-by: Martin Schwenke <martin at meltin.net>
    Reviewed-by: Amitay Isaacs <amitay at gmail.com>

commit f025f5c0a7c33faa4fbcffd6808999f403d164d4
Author: Martin Schwenke <martin at meltin.net>
Date:   Fri Oct 13 12:49:05 2017 +1100

    ctdb-tests: Have fake daemon log when it parses public IPs
    
    Signed-off-by: Martin Schwenke <martin at meltin.net>
    Reviewed-by: Amitay Isaacs <amitay at gmail.com>

commit 28d6356a65eac558d095af53c5d396f884a3b59f
Author: Martin Schwenke <martin at meltin.net>
Date:   Wed Oct 18 20:08:19 2017 +1100

    ctdb-common: Ensure unused bytes in union are initialised
    
    Signed-off-by: Martin Schwenke <martin at meltin.net>
    Reviewed-by: Amitay Isaacs <amitay at gmail.com>

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

Summary of changes:
 ctdb/common/ctdb_util.c                  |  44 ++++++--
 ctdb/common/sock_daemon.c                |  31 +++---
 ctdb/config/ctdbd_wrapper                |  18 +--
 ctdb/tests/cunit/sock_daemon_test_001.sh |  11 ++
 ctdb/tests/src/fake_ctdbd.c              |  12 +-
 ctdb/tests/src/sock_daemon_test.c        | 183 +++++++++++++++++++++++++++++--
 6 files changed, 250 insertions(+), 49 deletions(-)


Changeset truncated at 500 lines:

diff --git a/ctdb/common/ctdb_util.c b/ctdb/common/ctdb_util.c
index 901e5e2..82526b5 100644
--- a/ctdb/common/ctdb_util.c
+++ b/ctdb/common/ctdb_util.c
@@ -373,19 +373,45 @@ struct ctdb_rec_data_old *ctdb_marshall_loop_next(
 */
 void ctdb_canonicalize_ip(const ctdb_sock_addr *ip, ctdb_sock_addr *cip)
 {
-	char prefix[12] = { 0,0,0,0,0,0,0,0,0,0,0xff,0xff };
+	ZERO_STRUCTP(cip);
 
-	memcpy(cip, ip, sizeof (*cip));
-
-	if ( (ip->sa.sa_family == AF_INET6)
-	&& !memcmp(&ip->ip6.sin6_addr, prefix, 12)) {
-		memset(cip, 0, sizeof(*cip));
+	if (ip->sa.sa_family == AF_INET6) {
+		const char prefix[12] = { 0,0,0,0,0,0,0,0,0,0,0xff,0xff };
+		if (memcmp(&ip->ip6.sin6_addr, prefix, sizeof(prefix)) == 0) {
+			/* Copy IPv4-mapped IPv6 addresses as IPv4 */
+			cip->ip.sin_family = AF_INET;
+#ifdef HAVE_SOCK_SIN_LEN
+			cip->ip.sin_len = sizeof(ctdb_sock_addr);
+#endif
+			cip->ip.sin_port   = ip->ip6.sin6_port;
+			memcpy(&cip->ip.sin_addr,
+			       &ip->ip6.sin6_addr.s6_addr[12],
+			       sizeof(cip->ip.sin_addr));
+		} else {
+			cip->ip6.sin6_family = AF_INET6;
 #ifdef HAVE_SOCK_SIN_LEN
-		cip->ip.sin_len = sizeof(*cip);
+			cip->ip6.sin_len = sizeof(ctdb_sock_addr);
 #endif
+			cip->ip6.sin6_port   = ip->ip6.sin6_port;
+			memcpy(&cip->ip6.sin6_addr,
+			       &ip->ip6.sin6_addr,
+			       sizeof(cip->ip6.sin6_addr));
+		}
+
+		return;
+	}
+
+	if (ip->sa.sa_family == AF_INET) {
 		cip->ip.sin_family = AF_INET;
-		cip->ip.sin_port   = ip->ip6.sin6_port;
-		memcpy(&cip->ip.sin_addr, &ip->ip6.sin6_addr.s6_addr[12], 4);
+#ifdef HAVE_SOCK_SIN_LEN
+		cip->ip.sin_len = sizeof(ctdb_sock_addr);
+#endif
+		cip->ip.sin_port = ip->ip.sin_port;
+		memcpy(&cip->ip.sin_addr,
+		       &ip->ip.sin_addr,
+		       sizeof(ip->ip.sin_addr));
+
+		return;
 	}
 }
 
diff --git a/ctdb/common/sock_daemon.c b/ctdb/common/sock_daemon.c
index 56205d0..ba171af 100644
--- a/ctdb/common/sock_daemon.c
+++ b/ctdb/common/sock_daemon.c
@@ -239,6 +239,8 @@ static int socket_setup(const char *sockpath, bool remove_before_use)
 		return -1;
 	}
 
+	D_NOTICE("listening on %s\n", sockpath);
+
 	return fd;
 }
 
@@ -247,7 +249,6 @@ static int sock_socket_destructor(struct sock_socket *sock);
 static int sock_socket_init(TALLOC_CTX *mem_ctx, const char *sockpath,
 			    struct sock_socket_funcs *funcs,
 			    void *private_data,
-			    bool remove_before_use,
 			    struct sock_socket **result)
 {
 	struct sock_socket *sock;
@@ -267,12 +268,7 @@ static int sock_socket_init(TALLOC_CTX *mem_ctx, const char *sockpath,
 	sock->sockpath = sockpath;
 	sock->funcs = funcs;
 	sock->private_data = private_data;
-
-	sock->fd = socket_setup(sockpath, remove_before_use);
-	if (sock->fd == -1) {
-		talloc_free(sock);
-		return EIO;
-	}
+	sock->fd = -1;
 
 	talloc_set_destructor(sock, sock_socket_destructor);
 
@@ -306,7 +302,8 @@ static int sock_socket_start_client_destructor(struct sock_client *client);
 
 static struct tevent_req *sock_socket_start_send(TALLOC_CTX *mem_ctx,
 						 struct tevent_context *ev,
-						 struct sock_socket *sock)
+						 struct sock_socket *sock,
+						 bool remove_before_use)
 {
 	struct tevent_req *req, *subreq;
 	struct sock_socket_start_state *state;
@@ -320,6 +317,12 @@ static struct tevent_req *sock_socket_start_send(TALLOC_CTX *mem_ctx,
 	state->ev = ev;
 	state->sock = sock;
 
+	sock->fd = socket_setup(sock->sockpath, remove_before_use);
+	if (sock->fd == -1) {
+		tevent_req_error(req, EIO);
+		return tevent_req_post(req, ev);
+	}
+
 	talloc_set_destructor(state, sock_socket_start_state_destructor);
 
 	subreq = accept_send(state, ev, sock->fd);
@@ -487,17 +490,12 @@ int sock_daemon_add_unix(struct sock_daemon_context *sockd,
 {
 	struct sock_socket *sock;
 	int ret;
-	bool remove_before_use = false;
 
-	remove_before_use = (sockd->pid_ctx != NULL) ? true : false;
-
-	ret = sock_socket_init(sockd, sockpath, funcs, private_data,
-			       remove_before_use, &sock);
+	ret = sock_socket_init(sockd, sockpath, funcs, private_data, &sock);
 	if (ret != 0) {
 		return ret;
 	}
 
-	D_NOTICE("listening on %s\n", sockpath);
 
 	DLIST_ADD(sockd->socket_list, sock);
 	return 0;
@@ -537,6 +535,7 @@ struct tevent_req *sock_daemon_run_send(TALLOC_CTX *mem_ctx,
 	struct sock_daemon_run_state *state;
 	struct tevent_signal *se;
 	struct sock_socket *sock;
+	bool remove_before_use = false;
 
 	req = tevent_req_create(mem_ctx, &state,
 				struct sock_daemon_run_state);
@@ -553,6 +552,7 @@ struct tevent_req *sock_daemon_run_send(TALLOC_CTX *mem_ctx,
 			tevent_req_error(req, EEXIST);
 			return tevent_req_post(req, ev);
 		}
+		remove_before_use = true;
 	}
 
 	state->ev = ev;
@@ -592,7 +592,8 @@ struct tevent_req *sock_daemon_run_send(TALLOC_CTX *mem_ctx,
 	}
 
 	for (sock = sockd->socket_list; sock != NULL; sock = sock->next) {
-		subreq = sock_socket_start_send(state, ev, sock);
+		subreq = sock_socket_start_send(state, ev, sock,
+						remove_before_use);
 		if (tevent_req_nomem(subreq, req)) {
 			return tevent_req_post(req, ev);
 		}
diff --git a/ctdb/config/ctdbd_wrapper b/ctdb/config/ctdbd_wrapper
index 8a9f554..8eec379 100755
--- a/ctdb/config/ctdbd_wrapper
+++ b/ctdb/config/ctdbd_wrapper
@@ -227,22 +227,8 @@ start()
     _timeout="${CTDB_STARTUP_TIMEOUT:-10}"
     _count=0
     while [ "$_count" -lt "$_timeout" ] ; do
-	# If we don't have the PID then try to read it.
-	[ -n "$_pid" ] || read _pid 2>/dev/null <"$pidfile"
-
-	# If we got the PID but the PID file has gone or the process
-	# is no longer running then stop waiting... CTDB is dead.
-	if [ -n "$_pid" ] ; then
-	    if [ ! -e "$pidfile" ] || ! kill -0 "$_pid" 2>/dev/null ; then
-		echo "CTDB exited during initialisation - check logs."
-		kill_ctdbd "$_pid"
-		drop_all_public_ips >/dev/null 2>&1
-		return 1
-	    fi
-
-	    if $CTDB runstate first_recovery startup running >/dev/null 2>&1 ; then
-		return 0
-	    fi
+	if $CTDB runstate first_recovery startup running >/dev/null 2>&1 ; then
+	    return 0
 	fi
 
 	_count=$((_count + 1))
diff --git a/ctdb/tests/cunit/sock_daemon_test_001.sh b/ctdb/tests/cunit/sock_daemon_test_001.sh
index 1d2607f..9da484a 100755
--- a/ctdb/tests/cunit/sock_daemon_test_001.sh
+++ b/ctdb/tests/cunit/sock_daemon_test_001.sh
@@ -24,6 +24,7 @@ result_filter ()
 
 ok <<EOF
 test1[PID]: listening on $sockpath
+test1[PID]: Shutting down
 EOF
 unit_test sock_daemon_test "$pidfile" "$sockpath" 1
 
@@ -92,3 +93,13 @@ test9[PID]: Received signal 15
 test9[PID]: Shutting down
 EOF
 unit_test sock_daemon_test "$pidfile" "$sockpath" 9
+
+ok <<EOF
+test10[PID]: listening on $sockpath
+test10[PID]: daemon started, pid=PID
+test10[PID]: listening on $sockpath
+test10[PID]: daemon started, pid=PID
+test10[PID]: Received signal 15
+test10[PID]: Shutting down
+EOF
+unit_test sock_daemon_test "$pidfile" "$sockpath" 10
diff --git a/ctdb/tests/src/fake_ctdbd.c b/ctdb/tests/src/fake_ctdbd.c
index af56e08..2f4e87f 100644
--- a/ctdb/tests/src/fake_ctdbd.c
+++ b/ctdb/tests/src/fake_ctdbd.c
@@ -737,6 +737,8 @@ static struct database *database_find(struct database_map *map,
 static bool public_ips_parse(struct ctdbd_context *ctdb,
 			     uint32_t numnodes)
 {
+	bool status;
+
 	if (numnodes == 0) {
 		D_ERR("Must initialise nodemap before public IPs\n");
 		return false;
@@ -744,7 +746,15 @@ static bool public_ips_parse(struct ctdbd_context *ctdb,
 
 	ctdb->known_ips = ipalloc_read_known_ips(ctdb, numnodes, false);
 
-	return (ctdb->known_ips != NULL);
+	status = (ctdb->known_ips != NULL);
+
+	if (status) {
+		D_INFO("Parsing public IPs done\n");
+	} else {
+		D_INFO("Parsing public IPs failed\n");
+	}
+
+	return status;
 }
 
 /* Read information about controls to fail.  Format is:
diff --git a/ctdb/tests/src/sock_daemon_test.c b/ctdb/tests/src/sock_daemon_test.c
index 95b0909..bba0df2 100644
--- a/ctdb/tests/src/sock_daemon_test.c
+++ b/ctdb/tests/src/sock_daemon_test.c
@@ -32,6 +32,42 @@
 #include "common/sock_daemon.c"
 #include "common/sock_io.c"
 
+struct dummy_wait_state {
+};
+
+static struct tevent_req *dummy_wait_send(TALLOC_CTX *mem_ctx,
+					  struct tevent_context *ev,
+					  void *private_data)
+{
+	struct tevent_req *req;
+	struct dummy_wait_state *state;
+	const char *sockpath = (const char *)private_data;
+	struct stat st;
+	int ret;
+
+	ret = stat(sockpath, &st);
+	assert(ret == 0);
+	assert(S_ISSOCK(st.st_mode));
+
+	req = tevent_req_create(mem_ctx, &state, struct dummy_wait_state);
+	if (req == NULL) {
+		return NULL;
+	}
+
+	tevent_req_done(req);
+	return tevent_req_post(req, ev);
+}
+
+static bool dummy_wait_recv(struct tevent_req *req, int *perr)
+{
+	return true;
+}
+
+static struct sock_daemon_funcs test1_funcs = {
+	.wait_send = dummy_wait_send,
+	.wait_recv = dummy_wait_recv,
+};
+
 static struct tevent_req *dummy_read_send(TALLOC_CTX *mem_ctx,
 					  struct tevent_context *ev,
 					  struct sock_client_context *client,
@@ -63,12 +99,13 @@ static struct sock_socket_funcs dummy_socket_funcs = {
 static void test1(TALLOC_CTX *mem_ctx, const char *pidfile,
 		  const char *sockpath)
 {
+	struct tevent_context *ev;
 	struct sock_daemon_context *sockd;
 	struct stat st;
 	int ret;
 
 	ret = sock_daemon_setup(mem_ctx, "test1", "file:", "NOTICE",
-				NULL, NULL, &sockd);
+				&test1_funcs, discard_const(sockpath), &sockd);
 	assert(ret == 0);
 	assert(sockd != NULL);
 
@@ -79,16 +116,15 @@ static void test1(TALLOC_CTX *mem_ctx, const char *pidfile,
 	assert(ret == 0);
 
 	ret = stat(sockpath, &st);
-	assert(ret == 0);
-	assert(S_ISSOCK(st.st_mode));
+	assert(ret == -1);
 
-	talloc_free(sockd);
+	ev = tevent_context_init(mem_ctx);
+	assert(ev != NULL);
 
-	ret = stat(pidfile, &st);
-	assert(ret == -1);
+	ret = sock_daemon_run(ev, sockd, NULL, false, false, -1);
+	assert(ret == 0);
 
-	ret = stat(sockpath, &st);
-	assert(ret == -1);
+	talloc_free(mem_ctx);
 }
 
 /*
@@ -1299,6 +1335,133 @@ static void test9(TALLOC_CTX *mem_ctx, const char *pidfile,
 	close(fd[0]);
 }
 
+/*
+ * test10
+ *
+ * Confirm that the daemon starts successfully if there is a stale socket
+ */
+
+static void test10(TALLOC_CTX *mem_ctx, const char *pidfile,
+		  const char *sockpath)
+{
+	struct stat st;
+	int fd[2];
+	pid_t pid, pid2;
+	int ret;
+	ssize_t n;
+	int pidfile_fd;
+	char pidstr[20] = { 0 };
+
+	ret = pipe(fd);
+	assert(ret == 0);
+
+	pid = fork();
+	assert(pid != -1);
+
+	if (pid == 0) {
+		struct tevent_context *ev;
+		struct sock_daemon_context *sockd;
+
+		close(fd[0]);
+
+		ev = tevent_context_init(mem_ctx);
+		assert(ev != NULL);
+
+		ret = sock_daemon_setup(mem_ctx, "test10", "file:", "NOTICE",
+					&test2_funcs, &fd[1], &sockd);
+		assert(ret == 0);
+
+		ret = sock_daemon_add_unix(sockd, sockpath,
+					   &dummy_socket_funcs, NULL);
+		assert(ret == 0);
+
+		ret = sock_daemon_run(ev, sockd, pidfile, false, false, -1);
+		assert(ret == EINTR);
+
+		exit(0);
+	}
+
+	close(fd[1]);
+
+	n = read(fd[0], &ret, sizeof(ret));
+	assert(n == sizeof(ret));
+	assert(ret == 1);
+
+	/* KILL will leave PID file and socket behind */
+	ret = kill (pid, SIGKILL);
+	assert(ret == 0);
+
+	ret = stat(sockpath, &st);
+	assert(ret == 0);
+
+	close(fd[0]);
+
+	ret = pipe(fd);
+	assert(ret == 0);
+
+	pid = fork();
+	assert(pid != -1);
+
+	if (pid == 0) {
+		struct tevent_context *ev;
+		struct sock_daemon_context *sockd;
+
+		close(fd[0]);
+
+		ev = tevent_context_init(mem_ctx);
+		assert(ev != NULL);
+
+		ret = sock_daemon_setup(mem_ctx, "test10", "file:", "NOTICE",
+					&test2_funcs, &fd[1], &sockd);
+		assert(ret == 0);
+
+		ret = sock_daemon_add_unix(sockd, sockpath,
+					   &dummy_socket_funcs, NULL);
+		assert(ret == 0);
+
+		ret = sock_daemon_run(ev, sockd, pidfile, false, false, -1);
+		assert(ret == EINTR);
+
+		exit(0);
+	}
+
+	close(fd[1]);
+
+	n = read(fd[0], &ret, sizeof(ret));
+	assert(n == sizeof(ret));
+	assert(ret == 1);
+
+	ret = stat(pidfile, &st);
+	assert(ret == 0);
+	assert(S_ISREG(st.st_mode));
+
+	pidfile_fd = open(pidfile, O_RDONLY, 0644);
+	assert(pidfile_fd != -1);
+	n = read(pidfile_fd, pidstr, sizeof(pidstr)-1);
+	assert(n != -1);
+	pid2 = (pid_t)atoi(pidstr);
+	assert(pid == pid2);
+
+	ret = kill(pid, SIGTERM);
+	assert(ret == 0);
+
+	n = read(fd[0], &ret, sizeof(ret));
+	assert(n == sizeof(ret));
+	assert(ret == 3);
+
+	pid2 = waitpid(pid, &ret, 0);
+	assert(pid2 == pid);
+	assert(WEXITSTATUS(ret) == 0);
+
+	close(fd[0]);
+
+	ret = stat(pidfile, &st);
+	assert(ret == -1);
+
+	ret = stat(sockpath, &st);
+	assert(ret == -1);
+}
+
 int main(int argc, const char **argv)
 {
 	TALLOC_CTX *mem_ctx;
@@ -1354,6 +1517,10 @@ int main(int argc, const char **argv)
 		test9(mem_ctx, pidfile, sockpath);
 		break;
 
+	case 10:
+		test10(mem_ctx, pidfile, sockpath);
+		break;
+
 	default:
 		fprintf(stderr, "Unknown test number %d\n", num);
 	}


-- 
Samba Shared Repository



More information about the samba-cvs mailing list