From 32ffc06c0706f51c3f1dc436911836f1f9aa326e Mon Sep 17 00:00:00 2001 From: Andre Noll Date: Sun, 26 Feb 2012 14:14:18 +0100 Subject: [PATCH] Pass command exit status via sideband to client. 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 | 1 + client_common.c | 26 ++++++++++++++++++++------ command.c | 10 +++++++++- error.h | 2 ++ 4 files changed, 32 insertions(+), 7 deletions(-) diff --git a/client.c b/client.c index 4998222e..c194e192 100644 --- 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: diff --git a/client_common.c b/client_common.c index daead879..649a1b4f 100644 --- a/client_common.c +++ b/client_common.c @@ -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); } diff --git a/command.c b/command.c index 7b474ab1..2cac57f9 100644 --- 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 8ebf4ef8..3100b312 100644 --- 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 \ -- 2.39.2