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.
}
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));
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",
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;
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)
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;
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;
void *query_shm;
struct callback_query *cq;
struct osl_object query;
void *query_shm;
struct callback_query *cq;
struct osl_object query;
ret = shm_attach(query_shmid, ATTACH_RW, &query_shm);
if (ret < 0)
ret = shm_attach(query_shmid, ATTACH_RW, &query_shm);
if (ret < 0)
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)
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);
free(opts->data);
free(opts->data_ptr);
free(opts->patterns);
free(opts->data);
free(opts->data_ptr);
free(opts->patterns);
*/
int com_ls(struct command_context *cc)
{
*/
int com_ls(struct command_context *cc)
{
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;
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);
__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);
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 \
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