ctdb-tests: Do not attempt to unregister the join handler multiple times
authorAmitay Isaacs <amitay@gmail.com>
Thu, 5 Jan 2017 04:05:56 +0000 (15:05 +1100)
committerMartin Schwenke <martins@samba.org>
Fri, 6 Jan 2017 11:27:23 +0000 (12:27 +0100)
MSG_ID_SYNC is broadcast to each node when a MSG_ID_JOIN has been
received from all nodes.  After MSG_ID_SYNC is successfully broadcast,
the join handler is unregistered.  However, if another MSG_ID_JOIN is
received before the join handler is unregistered then MSG_ID_SYNC is
re-broadcast.  This results in multiple attempts to unregister the
join handler.

Once all MSG_ID_JOIN messages are received, unregister the join handler
to ignore any extra MSG_ID_JOIN messages.  Also, make sure that while
join handler is being unregistered, MSG_ID_JOIN messages are ignored.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=12500

Identified-by: Martin Schwenke <martin@meltin.net>
Signed-off-by: Amitay Isaacs <amitay@gmail.com>
Reviewed-by: Martin Schwenke <martin@meltin.net>
Autobuild-User(master): Martin Schwenke <martins@samba.org>
Autobuild-Date(master): Fri Jan  6 12:27:23 CET 2017 on sn-devel-144

ctdb/tests/src/cluster_wait.c

index ddc3e02cbfffb6a15172f8a024207c4ebcfe8dea..1405738ac47170b26a02642161b172f6ba4f647f 100644 (file)
@@ -36,6 +36,7 @@ struct cluster_wait_state {
        struct ctdb_client_context *client;
        int num_nodes;
        bool *ready;
+       bool join_done;
 };
 
 static void cluster_wait_join_registered(struct tevent_req *subreq);
@@ -44,8 +45,8 @@ static void cluster_wait_join(struct tevent_req *subreq);
 static void cluster_wait_join_sent(struct tevent_req *subreq);
 static void cluster_wait_join_handler(uint64_t srvid, TDB_DATA data,
                                      void *private_data);
-static void cluster_wait_sync_sent(struct tevent_req *subreq);
 static void cluster_wait_join_unregistered(struct tevent_req *subreq);
+static void cluster_wait_sync_sent(struct tevent_req *subreq);
 static void cluster_wait_sync_handler(uint64_t srvid, TDB_DATA data,
                                      void *private_data);
 static void cluster_wait_sync_unregistered(struct tevent_req *subreq);
@@ -67,6 +68,8 @@ struct tevent_req *cluster_wait_send(TALLOC_CTX *mem_ctx,
        state->client = client;
        state->num_nodes = num_nodes;
 
+       state->join_done = false;
+
        if (ctdb_client_pnn(client) == 0) {
                state->ready = talloc_zero_array(state, bool, num_nodes);
                if (tevent_req_nomem(state->ready, req)) {
@@ -201,7 +204,6 @@ static void cluster_wait_join_handler(uint64_t srvid, TDB_DATA data,
                private_data, struct tevent_req);
        struct cluster_wait_state *state = tevent_req_data(
                req, struct cluster_wait_state);
-       struct ctdb_req_message msg;
        struct tevent_req *subreq;
        uint32_t pnn;
        int i;
@@ -228,50 +230,56 @@ static void cluster_wait_join_handler(uint64_t srvid, TDB_DATA data,
                }
        }
 
-       msg.srvid = MSG_ID_SYNC;
-       msg.data.data = tdb_null;
+       if (state->join_done) {
+               return;
+       }
 
-       subreq = ctdb_client_message_send(state, state->ev, state->client,
-                                         CTDB_BROADCAST_ALL, &msg);
+       state->join_done = true;
+       subreq = ctdb_client_remove_message_handler_send(
+                                       state, state->ev, state->client,
+                                       MSG_ID_JOIN, req);
        if (tevent_req_nomem(subreq, req)) {
                return;
        }
-       tevent_req_set_callback(subreq, cluster_wait_sync_sent, req);
+       tevent_req_set_callback(subreq, cluster_wait_join_unregistered, req);
 }
 
-static void cluster_wait_sync_sent(struct tevent_req *subreq)
+static void cluster_wait_join_unregistered(struct tevent_req *subreq)
 {
        struct tevent_req *req = tevent_req_callback_data(
                subreq, struct tevent_req);
        struct cluster_wait_state *state = tevent_req_data(
                req, struct cluster_wait_state);
+       struct ctdb_req_message msg;
        bool status;
        int ret;
 
-       status = ctdb_client_message_recv(subreq, &ret);
-       TALLOC_FREE(subreq);
+       status = ctdb_client_remove_message_handler_recv(subreq, &ret);
        if (! status) {
                tevent_req_error(req, ret);
                return;
        }
 
-       subreq = ctdb_client_remove_message_handler_send(
-                                       state, state->ev, state->client,
-                                       MSG_ID_JOIN, req);
+       msg.srvid = MSG_ID_SYNC;
+       msg.data.data = tdb_null;
+
+       subreq = ctdb_client_message_send(state, state->ev, state->client,
+                                         CTDB_BROADCAST_ALL, &msg);
        if (tevent_req_nomem(subreq, req)) {
                return;
        }
-       tevent_req_set_callback(subreq, cluster_wait_join_unregistered, req);
+       tevent_req_set_callback(subreq, cluster_wait_sync_sent, req);
 }
 
-static void cluster_wait_join_unregistered(struct tevent_req *subreq)
+static void cluster_wait_sync_sent(struct tevent_req *subreq)
 {
        struct tevent_req *req = tevent_req_callback_data(
                subreq, struct tevent_req);
        bool status;
        int ret;
 
-       status = ctdb_client_remove_message_handler_recv(subreq, &ret);
+       status = ctdb_client_message_recv(subreq, &ret);
+       TALLOC_FREE(subreq);
        if (! status) {
                tevent_req_error(req, ret);
                return;