]> git.ipfire.org Git - thirdparty/lxc.git/commitdiff
commands: tweak locking
authorChristian Brauner <christian.brauner@ubuntu.com>
Fri, 24 Nov 2017 11:51:04 +0000 (12:51 +0100)
committerChristian Brauner <christian.brauner@ubuntu.com>
Wed, 6 Dec 2017 15:01:23 +0000 (16:01 +0100)
Take the lock on the list after we've done all necessary work and check state.
If we are in requested state, do cleanup and return without adding the state
client to the state client list.

Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
src/lxc/commands.c
src/lxc/commands_utils.c
src/lxc/start.c

index d7e41e5a738ce94d3bc2f08df5fe8a630944267e..d95530ec7ab5aae42a9e7b234c1188f1efb30aeb 100644 (file)
@@ -893,9 +893,8 @@ int lxc_cmd_add_state_client(const char *name, const char *lxcpath,
                             lxc_state_t states[MAX_STATE],
                             int *state_client_fd)
 {
-       int stopped;
+       int state, stopped;
        ssize_t ret;
-       int state = -1;
        struct lxc_cmd_rr cmd = {
            .req = {
                .cmd     = LXC_CMD_ADD_STATE_CLIENT,
@@ -904,17 +903,10 @@ int lxc_cmd_add_state_client(const char *name, const char *lxcpath,
            },
        };
 
-       /* Check if already in requested state. */
-       state = lxc_getstate(name, lxcpath);
-       if (state < 0) {
-               TRACE("%s - Failed to retrieve state of container", strerror(errno));
-               return -1;
-       } else if (states[state] == 1) {
-               TRACE("Container is in %s state", lxc_state2str(state));
-               return state;
-       }
-
        ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL);
+       if (states[STOPPED] != 0 && stopped != 0)
+               return STOPPED;
+
        if (ret < 0) {
                ERROR("%s - Failed to execute command", strerror(errno));
                return -1;
@@ -924,11 +916,19 @@ int lxc_cmd_add_state_client(const char *name, const char *lxcpath,
         * function.
         */
        if (cmd.rsp.ret < 0) {
-               ERROR("Failed to receive socket fd");
+               ERROR("%s - Failed to receive socket fd", strerror(-cmd.rsp.ret));
                return -1;
        }
 
+       state = PTR_TO_INT(cmd.rsp.data);
+       if (state < MAX_STATE) {
+               TRACE("Container is already in requested state %s",
+                     lxc_state2str(state));
+               return state;
+       }
+
        *state_client_fd = cmd.rsp.ret;
+       TRACE("Added state client %d to state client list", cmd.rsp.ret);
        return MAX_STATE;
 }
 
@@ -947,10 +947,7 @@ static int lxc_cmd_add_state_client_callback(int fd, struct lxc_cmd_req *req,
                return -1;
 
        rsp.ret = lxc_add_state_client(fd, handler, (lxc_state_t *)req->data);
-       if (rsp.ret < 0)
-               ERROR("Failed to add state client %d to state client list", fd);
-       else
-               TRACE("Added state client %d to state client list", fd);
+       rsp.data = INT_TO_PTR(rsp.ret);
 
        return lxc_cmd_rsp_send(fd, &rsp);
 }
index 394f0a1d7c3bdc6dc43ab73bb25ff166decddf57..32831e2b61644669231f568fa051c849653026f8 100644 (file)
@@ -193,6 +193,7 @@ int lxc_cmd_connect(const char *name, const char *lxcpath,
 int lxc_add_state_client(int state_client_fd, struct lxc_handler *handler,
                         lxc_state_t states[MAX_STATE])
 {
+       int state;
        struct lxc_state_client *newclient;
        struct lxc_list *tmplist;
 
@@ -211,11 +212,17 @@ int lxc_add_state_client(int state_client_fd, struct lxc_handler *handler,
        }
 
        process_lock();
-       lxc_list_add_elem(tmplist, newclient);
-       lxc_list_add_tail(&handler->conf->state_clients, tmplist);
-       process_unlock();
+       state = handler->state;
+       if (states[state] != 1) {
+               lxc_list_add_elem(tmplist, newclient);
+               lxc_list_add_tail(&handler->conf->state_clients, tmplist);
+               process_unlock();
+       } else {
+               process_unlock();
+               free(newclient);
+               return state;
+       }
 
        TRACE("added state client %d to state client list", state_client_fd);
-
-       return 0;
+       return MAX_STATE;
 }
index ce13a3c50a504bb876c1f73c17c3e59979b5f4ad..72e3f0146e6c7eac90cbd2b32fbd2f6df73c6a51 100644 (file)
@@ -358,10 +358,10 @@ static int lxc_serve_state_clients(const char *name,
        struct lxc_state_client *client;
        struct lxc_msg msg = {.type = lxc_msg_state, .value = state};
 
+       process_lock();
        handler->state = state;
        TRACE("Set container state to %s", lxc_state2str(state));
 
-       process_lock();
        if (lxc_list_empty(&handler->conf->state_clients)) {
                TRACE("No state clients registered");
                process_unlock();