Pass command exit status via sideband to client.
authorAndre Noll <maan@systemlinux.org>
Sun, 26 Feb 2012 13:14:18 +0000 (14:14 +0100)
committerAndre Noll <maan@systemlinux.org>
Mon, 7 May 2012 10:59:07 +0000 (12:59 +0200)
Currently the only way for the client side to tell whether a command
failed is to parse the command output. This patch changes command.c to
send an empty sideband packet at command termination. If the command
succeeded, the sideband designator is set to SBD_EXIT__SUCCESS,
otherwise it is SBD_EXIT__FAILURE.

The client checks for these sideband packets and terminates with
EXIT_FAILURE if it received the SBD_EXIT__FAILURE packet.

client.c
client_common.c
command.c
error.h

index 4998222..c194e19 100644 (file)
--- a/client.c
+++ b/client.c
@@ -606,6 +606,7 @@ int main(int argc, char *argv[])
        if (ret >= 0 && ct->task.error < 0) {
                switch(ct->task.error) {
                /* these are not errors */
+               case -E_SERVER_CMD_SUCCESS:
                case -E_EOF:
                case -E_SERVER_EOF:
                case -E_BTR_EOF:
index daead87..649a1b4 100644 (file)
@@ -242,14 +242,19 @@ static char **parse_features(char *buf)
 
 static int dispatch_sbb(struct client_task *ct, struct sb_buffer *sbb)
 {
-       int ret, ll;
+       int ret;
+       const char *designator[] = {SB_DESIGNATORS_ARRAY};
 
-       if (!sbb || !sbb->iov.iov_base || sbb->iov.iov_len == 0)
+       if (!sbb)
                return 0;
+       if (sbb->band < NUM_SB_DESIGNATORS)
+               PARA_DEBUG_LOG("band: %s\n", designator[sbb->band]);
 
        switch (sbb->band) {
        case SBD_OUTPUT:
-               btr_add_output(sbb->iov.iov_base, sbb->iov.iov_len, ct->btrn);
+               if (iov_valid(&sbb->iov))
+                       btr_add_output(sbb->iov.iov_base, sbb->iov.iov_len,
+                               ct->btrn);
                ret = 1;
                goto out;
        case SBD_DEBUG_LOG:
@@ -259,10 +264,18 @@ static int dispatch_sbb(struct client_task *ct, struct sb_buffer *sbb)
        case SBD_ERROR_LOG:
        case SBD_CRIT_LOG:
        case SBD_EMERG_LOG:
-               ll = sbb->band - SBD_DEBUG_LOG;
-               para_log(ll, "remote: %s", (char *)sbb->iov.iov_base);
+               if (iov_valid(&sbb->iov)) {
+                       int ll = sbb->band - SBD_DEBUG_LOG;
+                       para_log(ll, "remote: %s", (char *)sbb->iov.iov_base);
+               }
                ret = 1;
                goto deallocate;
+       case SBD_EXIT__SUCCESS:
+               ret = -E_SERVER_CMD_SUCCESS;
+               goto deallocate;
+       case SBD_EXIT__FAILURE:
+               ret = -E_SERVER_CMD_FAILURE;
+               goto deallocate;
        default:
                PARA_ERROR_LOG("invalid band %d\n", sbb->band);
                ret = -E_BAD_BAND;
@@ -546,7 +559,8 @@ static void client_post_select(struct sched *s, struct task *t)
 out:
        t->error = ret;
        if (ret < 0) {
-               if (ret != -E_SERVER_EOF && ret != -E_BTR_EOF && ret != -E_EOF)
+               if (!ct->use_sideband && ret != -E_SERVER_EOF &&
+                               ret != -E_BTR_EOF && ret != -E_EOF)
                        PARA_ERROR_LOG("%s\n", para_strerror(-t->error));
                btr_remove_node(btrn);
        }
index 7b474ab..2cac57f 100644 (file)
--- a/command.c
+++ b/command.c
@@ -1100,7 +1100,8 @@ __noreturn void handle_connect(int fd, const char *peername)
        if (ret >= 0)
                goto out;
 err_out:
-       send_strerror(cc, -ret);
+       if (send_strerror(cc, -ret) >= 0 && cc->use_sideband)
+               send_sb(&cc->scc, NULL, 0, SBD_EXIT__FAILURE, true);
 net_err:
        PARA_NOTICE_LOG("%s\n", para_strerror(-ret));
 out:
@@ -1113,5 +1114,12 @@ out:
                mmd->events++;
        mmd->active_connections--;
        mutex_unlock(mmd_mutex);
+       if (ret < 0)
+               exit(EXIT_FAILURE);
+       if (!cc->use_sideband)
+               exit(EXIT_SUCCESS);
+       ret = send_sb(&cc->scc, NULL, 0, SBD_EXIT__SUCCESS, true);
+       if (ret < 0)
+               PARA_NOTICE_LOG("%s\n", para_strerror(-ret));
        exit(ret < 0? EXIT_FAILURE : EXIT_SUCCESS);
 }
diff --git a/error.h b/error.h
index 8ebf4ef..3100b31 100644 (file)
--- a/error.h
+++ b/error.h
@@ -263,6 +263,8 @@ extern const char **para_errlist[];
        PARA_ERROR(BAD_CONFIG, "syntax error in config file"), \
        PARA_ERROR(CLIENT_AUTH, "authentication failed"), \
        PARA_ERROR(SERVER_EOF, "connection closed by para_server"), \
+       PARA_ERROR(SERVER_CMD_SUCCESS, "command terminated successfully"), \
+       PARA_ERROR(SERVER_CMD_FAILURE, "command failed"), \
 
 
 #define SCHED_ERRORS \