ctdb-tests: Fix the implementation of process-exists in fake daemon
authorAmitay Isaacs <amitay@gmail.com>
Fri, 25 Aug 2017 06:54:47 +0000 (16:54 +1000)
committerAmitay Isaacs <amitay@samba.org>
Sat, 9 Sep 2017 08:53:10 +0000 (10:53 +0200)
Keep track of clients and their pids.

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

Signed-off-by: Amitay Isaacs <amitay@gmail.com>
Reviewed-by: Martin Schwenke <martin@meltin.net>
ctdb/tests/src/fake_ctdbd.c

index ef3f1c1b5723b4b7122f91fd87e49f4eda024e1e..f99e1a252ebe3ce0e50d63f1728185a6e618c1f9 100644 (file)
@@ -108,6 +108,13 @@ struct fake_control_failure {
        const char *comment;
 };
 
+struct ctdb_client {
+       struct ctdb_client *prev, *next;
+       struct ctdbd_context *ctdb;
+       pid_t pid;
+       void *state;
+};
+
 struct ctdbd_context {
        struct node_map *node_map;
        struct interface_map *iface_map;
@@ -126,6 +133,7 @@ struct ctdbd_context {
        char *reclock;
        struct ctdb_public_ip_list *known_ips;
        struct fake_control_failure *control_failures;
+       struct ctdb_client *client_list;
 };
 
 /*
@@ -824,6 +832,48 @@ fail:
        return false;
 }
 
+/*
+ * Manage clients
+ */
+
+static int ctdb_client_destructor(struct ctdb_client *client)
+{
+       DLIST_REMOVE(client->ctdb->client_list, client);
+       return 0;
+}
+
+static int client_add(struct ctdbd_context *ctdb, pid_t client_pid,
+                     void *client_state)
+{
+       struct ctdb_client *client;
+
+       client = talloc_zero(client_state, struct ctdb_client);
+       if (client == NULL) {
+               return ENOMEM;
+       }
+
+       client->ctdb = ctdb;
+       client->pid = client_pid;
+       client->state = client_state;
+
+       DLIST_ADD(ctdb->client_list, client);
+       talloc_set_destructor(client, ctdb_client_destructor);
+       return 0;
+}
+
+static void *client_find(struct ctdbd_context *ctdb, pid_t client_pid)
+{
+       struct ctdb_client *client;
+
+       for (client=ctdb->client_list; client != NULL; client=client->next) {
+               if (client->pid == client_pid) {
+                       return client->state;
+               }
+       }
+
+       return NULL;
+}
+
 /*
  * CTDB context setup
  */
@@ -1148,6 +1198,7 @@ struct client_state {
        int fd;
        struct ctdbd_context *ctdb;
        int pnn;
+       pid_t pid;
        struct comm_context *comm;
        struct srvid_register_state *rstate;
        int status;
@@ -1261,11 +1312,22 @@ static void control_process_exists(TALLOC_CTX *mem_ctx,
                                   struct ctdb_req_header *header,
                                   struct ctdb_req_control *request)
 {
+       struct client_state *state = tevent_req_data(
+               req, struct client_state);
+       struct ctdbd_context *ctdb = state->ctdb;
+       struct client_state *cstate;
        struct ctdb_reply_control reply;
 
        reply.rdata.opcode = request->opcode;
-       reply.status = kill(request->rdata.data.pid, 0);
-       reply.errmsg = NULL;
+
+       cstate = client_find(ctdb, request->rdata.data.pid);
+       if (cstate == NULL) {
+               reply.status = -1;
+               reply.errmsg = "No client for PID";
+       } else {
+               reply.status = kill(request->rdata.data.pid, 0);
+               reply.errmsg = NULL;
+       }
 
        client_send_control(req, header, &reply);
 }
@@ -2980,6 +3042,8 @@ static struct tevent_req *client_send(TALLOC_CTX *mem_ctx,
 {
        struct tevent_req *req;
        struct client_state *state;
+       struct ucred cr;
+       socklen_t crl = sizeof(struct ucred);
        int ret;
 
        req = tevent_req_create(mem_ctx, &state, struct client_state);
@@ -2992,6 +3056,13 @@ static struct tevent_req *client_send(TALLOC_CTX *mem_ctx,
        state->ctdb = ctdb;
        state->pnn = pnn;
 
+       ret = getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &cr, &crl);
+       if (ret != 0) {
+               tevent_req_error(req, ret);
+               return tevent_req_post(req, ev);
+       }
+       state->pid = cr.pid;
+
        ret = comm_setup(state, ev, fd, client_read_handler, req,
                         client_dead_handler, req, &state->comm);
        if (ret != 0) {
@@ -2999,6 +3070,12 @@ static struct tevent_req *client_send(TALLOC_CTX *mem_ctx,
                return tevent_req_post(req, ev);
        }
 
+       ret = client_add(ctdb, state->pid, state);
+       if (ret != 0) {
+               tevent_req_error(req, ret);
+               return tevent_req_post(req, ev);
+       }
+
        DEBUG(DEBUG_INFO, ("New client fd=%d\n", fd));
 
        return req;