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.
if (ret >= 0 && ct->task.error < 0) {
switch(ct->task.error) {
/* these are not errors */
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:
case -E_EOF:
case -E_SERVER_EOF:
case -E_BTR_EOF:
static int dispatch_sbb(struct client_task *ct, struct sb_buffer *sbb)
{
static int dispatch_sbb(struct client_task *ct, struct sb_buffer *sbb)
{
+ int ret;
+ const char *designator[] = {SB_DESIGNATORS_ARRAY};
- if (!sbb || !sbb->iov.iov_base || sbb->iov.iov_len == 0)
+ if (sbb->band < NUM_SB_DESIGNATORS)
+ PARA_DEBUG_LOG("band: %s\n", designator[sbb->band]);
switch (sbb->band) {
case SBD_OUTPUT:
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:
ret = 1;
goto out;
case SBD_DEBUG_LOG:
case SBD_ERROR_LOG:
case SBD_CRIT_LOG:
case SBD_EMERG_LOG:
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;
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;
default:
PARA_ERROR_LOG("invalid band %d\n", sbb->band);
ret = -E_BAD_BAND;
out:
t->error = ret;
if (ret < 0) {
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);
}
PARA_ERROR_LOG("%s\n", para_strerror(-t->error));
btr_remove_node(btrn);
}
if (ret >= 0)
goto out;
err_out:
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:
net_err:
PARA_NOTICE_LOG("%s\n", para_strerror(-ret));
out:
mmd->events++;
mmd->active_connections--;
mutex_unlock(mmd_mutex);
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);
}
exit(ret < 0? EXIT_FAILURE : EXIT_SUCCESS);
}
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(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"), \