afs: Pass sideband error packet on callback failures.
authorAndre Noll <maan@tuebingen.mpg.de>
Sat, 4 Apr 2015 23:20:00 +0000 (23:20 +0000)
committerAndre Noll <maan@tuebingen.mpg.de>
Wed, 12 Aug 2015 21:23:47 +0000 (23:23 +0200)
This changes the afs callback mechanism to honor negative return
values from a callback. We now send a special "callback failure"
sideband packet to the command handler in this case. This packet
contains the (negative) return value of the callback.

The dispatcher for afs callback results reads the error code and passes
it back via the callback request functions to the caller of the command
handler in handle_connect(). The latter already does the right thing:
It translates the error code into a string and sends this string to
the client.

This commit changes the callback of the ls command to return negative
on errors. With the patch applied the command

para_client ls /does/not/exist

now exits with status 1.

Other afs commands will make use of the new feature in subsequent
commits.

afs.c
aft.c
error.h
sideband.h

diff --git a/afs.c b/afs.c
index 24e737b67e3995c8723cd1d7ae7f72899554c322..4bc7871cac868a45a2d487cdf5761d9509f19bfa 100644 (file)
--- a/afs.c
+++ b/afs.c
@@ -166,13 +166,8 @@ static int dispatch_result(int result_shmid, callback_result_handler *handler,
        }
        result.size = cr->result_size;
        result.data = result_shm + sizeof(*cr);
        }
        result.size = cr->result_size;
        result.data = result_shm + sizeof(*cr);
-       if (result.size) {
-               assert(handler);
-               ret = handler(&result, cr->band, private_result_data);
-               if (ret < 0)
-                       PARA_NOTICE_LOG("result handler error: %s\n",
-                               para_strerror(-ret));
-       }
+       assert(handler);
+       ret = handler(&result, cr->band, private_result_data);
        ret2 = shm_detach(result_shm);
        if (ret2 < 0) {
                PARA_ERROR_LOG("detach failed: %s\n", para_strerror(-ret2));
        ret2 = shm_detach(result_shm);
        if (ret2 < 0) {
                PARA_ERROR_LOG("detach failed: %s\n", para_strerror(-ret2));
@@ -261,12 +256,10 @@ int send_callback_request(callback_function *f, struct osl_object *query,
                ret = *(int *) buf;
                assert(ret > 0);
                result_shmid = ret;
                ret = *(int *) buf;
                assert(ret > 0);
                result_shmid = ret;
-               if (!dispatch_error) {
-                       ret = dispatch_result(result_shmid, result_handler,
-                               private_result_data);
-                       if (ret < 0)
-                               dispatch_error = 1;
-               }
+               ret = dispatch_result(result_shmid, result_handler,
+                       private_result_data);
+               if (ret < 0 && dispatch_error >= 0)
+                       dispatch_error = ret;
                ret = shm_destroy(result_shmid);
                if (ret < 0)
                        PARA_CRIT_LOG("destroy result failed: %s\n",
                ret = shm_destroy(result_shmid);
                if (ret < 0)
                        PARA_CRIT_LOG("destroy result failed: %s\n",
@@ -278,8 +271,11 @@ out:
                PARA_CRIT_LOG("shm destroy error\n");
        if (fd >= 0)
                close(fd);
                PARA_CRIT_LOG("shm destroy error\n");
        if (fd >= 0)
                close(fd);
-//     PARA_DEBUG_LOG("callback_ret: %d\n", ret);
-       return ret < 0? ret : num_dispatched;
+       if (dispatch_error < 0)
+               return dispatch_error;
+       if (ret < 0)
+               return ret;
+       return num_dispatched;
 }
 
 /**
 }
 
 /**
@@ -559,9 +555,22 @@ int afs_cb_result_handler(struct osl_object *result, uint8_t band,
        struct command_context *cc = private;
 
        assert(cc);
        struct command_context *cc = private;
 
        assert(cc);
-       if (!result->size)
-               return 1;
-       return send_sb(&cc->scc, result->data, result->size, band, true);
+       switch (band) {
+       case SBD_OUTPUT:
+       case SBD_DEBUG_LOG:
+       case SBD_INFO_LOG:
+       case SBD_NOTICE_LOG:
+       case SBD_WARNING_LOG:
+       case SBD_ERROR_LOG:
+       case SBD_CRIT_LOG:
+       case SBD_EMERG_LOG:
+               assert(result->size > 0);
+               return send_sb(&cc->scc, result->data, result->size, band, true);
+       case SBD_AFS_CB_FAILURE:
+               return *(int *)(result->data);
+       default:
+               return -E_BAD_BAND;
+       }
 }
 
 void flush_and_free_pb(struct para_buffer *pb)
 }
 
 void flush_and_free_pb(struct para_buffer *pb)
@@ -808,8 +817,8 @@ int pass_buffer_as_shm(int fd, uint8_t band, const char *buf, size_t size)
        void *shm;
        struct callback_result *cr;
 
        void *shm;
        struct callback_result *cr;
 
-       if (!buf || !size)
-               return 0;
+       if (size == 0)
+               assert(band != SBD_OUTPUT);
        ret = shm_new(size + sizeof(*cr));
        if (ret < 0)
                return ret;
        ret = shm_new(size + sizeof(*cr));
        if (ret < 0)
                return ret;
@@ -820,7 +829,8 @@ int pass_buffer_as_shm(int fd, uint8_t band, const char *buf, size_t size)
        cr = shm;
        cr->result_size = size;
        cr->band = band;
        cr = shm;
        cr->result_size = size;
        cr->band = band;
-       memcpy(shm + sizeof(*cr), buf, size);
+       if (size > 0)
+               memcpy(shm + sizeof(*cr), buf, size);
        ret = shm_detach(shm);
        if (ret < 0)
                goto err;
        ret = shm_detach(shm);
        if (ret < 0)
                goto err;
@@ -838,7 +848,7 @@ static int call_callback(int fd, int query_shmid)
        void *query_shm;
        struct callback_query *cq;
        struct osl_object query;
        void *query_shm;
        struct callback_query *cq;
        struct osl_object query;
-       int ret;
+       int ret, ret2;
 
        ret = shm_attach(query_shmid, ATTACH_RW, &query_shm);
        if (ret < 0)
 
        ret = shm_attach(query_shmid, ATTACH_RW, &query_shm);
        if (ret < 0)
@@ -846,8 +856,23 @@ static int call_callback(int fd, int query_shmid)
        cq = query_shm;
        query.data = (char *)query_shm + sizeof(*cq);
        query.size = cq->query_size;
        cq = query_shm;
        query.data = (char *)query_shm + sizeof(*cq);
        query.size = cq->query_size;
-       cq->handler(fd, &query);
-       return shm_detach(query_shm);
+       ret = cq->handler(fd, &query);
+       ret2 = shm_detach(query_shm);
+       if (ret2 < 0) {
+               if (ret < 0) /* ignore (but log) detach error */
+                       PARA_ERROR_LOG("could not detach sma: %s\n",
+                               para_strerror(-ret2));
+               else
+                       ret = ret2;
+       }
+       if (ret < 0) {
+               ret2 = pass_buffer_as_shm(fd, SBD_AFS_CB_FAILURE,
+                       (const char *)&ret, sizeof(ret));
+               if (ret2 < 0)
+                       PARA_ERROR_LOG("could not pass cb failure packet: %s\n",
+                               para_strerror(-ret));
+       }
+       return ret;
 }
 
 static int execute_server_command(fd_set *rfds)
 }
 
 static int execute_server_command(fd_set *rfds)
diff --git a/aft.c b/aft.c
index acb6c6bf879f838976652ca3c48cfbf3ff75f70c..6b5e0b74c4e70edc6d75c3dfeec9f9594f942e7b 100644 (file)
--- a/aft.c
+++ b/aft.c
@@ -1323,8 +1323,7 @@ static int com_ls_callback(int fd, const struct osl_object *query)
        if (ret < 0)
                goto out;
        if (opts->num_matching_paths == 0) {
        if (ret < 0)
                goto out;
        if (opts->num_matching_paths == 0) {
-               if (opts->num_patterns > 0)
-                       para_printf(&b, "no matches\n");
+               ret = opts->num_patterns > 0? -E_NO_MATCH : 0;
                goto out;
        }
        ret = sort_matching_paths(opts);
                goto out;
        }
        ret = sort_matching_paths(opts);
@@ -1348,7 +1347,7 @@ out:
        free(opts->data);
        free(opts->data_ptr);
        free(opts->patterns);
        free(opts->data);
        free(opts->data_ptr);
        free(opts->patterns);
-       return 0;
+       return ret;
 }
 
 /*
 }
 
 /*
@@ -1356,7 +1355,7 @@ out:
  */
 int com_ls(struct command_context *cc)
 {
  */
 int com_ls(struct command_context *cc)
 {
-       int i, ret;
+       int i;
        unsigned flags = 0;
        enum ls_sorting_method sort = LS_SORT_BY_PATH;
        enum ls_listing_mode mode = LS_MODE_SHORT;
        unsigned flags = 0;
        enum ls_sorting_method sort = LS_SORT_BY_PATH;
        enum ls_listing_mode mode = LS_MODE_SHORT;
@@ -1465,9 +1464,8 @@ int com_ls(struct command_context *cc)
        opts.sorting = sort;
        opts.mode = mode;
        opts.num_patterns = cc->argc - i;
        opts.sorting = sort;
        opts.mode = mode;
        opts.num_patterns = cc->argc - i;
-       ret = send_option_arg_callback_request(&query, opts.num_patterns,
+       return send_option_arg_callback_request(&query, opts.num_patterns,
                cc->argv + i, com_ls_callback, afs_cb_result_handler, cc);
                cc->argv + i, com_ls_callback, afs_cb_result_handler, cc);
-       return ret;
 }
 
 /**
 }
 
 /**
@@ -1777,7 +1775,9 @@ static int get_row_pointer_from_result(struct osl_object *result,
                __a_unused uint8_t band, void *private)
 {
        struct osl_row **row = private;
                __a_unused uint8_t band, void *private)
 {
        struct osl_row **row = private;
-       *row = *(struct osl_row **)(result->data);
+
+       if (band == SBD_OUTPUT)
+               *row = *(struct osl_row **)(result->data);
        return 1;
 }
 
        return 1;
 }
 
diff --git a/error.h b/error.h
index 28ac9552315689124f2bfa1de0e50f874d2e9e61..96a0c9a3af5062c1cc4780a2ad1de58b7f50441f 100644 (file)
--- a/error.h
+++ b/error.h
@@ -275,6 +275,7 @@ extern const char **para_errlist[];
        PARA_ERROR(NO_AFHI, "audio format handler info required"), \
        PARA_ERROR(AFT_SYNTAX, "audio file table syntax error"), \
        PARA_ERROR(HASH_MISMATCH, "hash mismatch, consider re-add"), \
        PARA_ERROR(NO_AFHI, "audio format handler info required"), \
        PARA_ERROR(AFT_SYNTAX, "audio file table syntax error"), \
        PARA_ERROR(HASH_MISMATCH, "hash mismatch, consider re-add"), \
+       PARA_ERROR(NO_MATCH, "no matches"), \
 
 
 #define USER_LIST_ERRORS \
 
 
 #define USER_LIST_ERRORS \
index 9ce0bb61b06924ad3c7a6a8f4ac25b699ca3307f..c9b698f978634858ae3ff8c95150975677be35ac 100644 (file)
@@ -60,6 +60,8 @@
        DESIGNATOR(EXIT__FAILURE), \
        /* The next chunk of the blob (addblob commands only) */ \
        DESIGNATOR(BLOB_DATA), \
        DESIGNATOR(EXIT__FAILURE), \
        /* The next chunk of the blob (addblob commands only) */ \
        DESIGNATOR(BLOB_DATA), \
+       /* An afs callback failed. */ \
+       DESIGNATOR(AFS_CB_FAILURE), \
 
 /** Just prefix with \p SBD_. */
 #define DESIGNATOR(x) SBD_ ## x
 
 /** Just prefix with \p SBD_. */
 #define DESIGNATOR(x) SBD_ ## x