From: Andre Noll Date: Tue, 8 Dec 2015 06:39:04 +0000 (+0100) Subject: Merge branch 'refs/heads/t/strerror' X-Git-Tag: v0.5.6~91 X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=commitdiff_plain;h=030a9d5c9fe28328d5db977bf2c8ddbf7302673d;hp=-c Merge branch 'refs/heads/t/strerror' Was cooking in next since 2015-09-27. * refs/heads/t/strerror: error.h: Never call (para_)strerror() on osl errors. Clarify para_strerror(). error.h: Remove is_errno(). --- 030a9d5c9fe28328d5db977bf2c8ddbf7302673d diff --combined afs.c index bd705050,c4053746..46af53f8 --- a/afs.c +++ b/afs.c @@@ -130,7 -130,7 +130,7 @@@ extern uint32_t afs_socket_cookie */ struct callback_query { /** The function to be called. */ - callback_function *handler; + afs_callback *handler; /** The number of bytes of the query */ size_t query_size; }; @@@ -166,8 -166,13 +166,8 @@@ static int dispatch_result(int result_s } 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)); @@@ -201,7 -206,7 +201,7 @@@ * * \sa send_option_arg_callback_request(), send_standard_callback_request(). */ -int send_callback_request(callback_function *f, struct osl_object *query, +int send_callback_request(afs_callback *f, struct osl_object *query, callback_result_handler *result_handler, void *private_result_data) { @@@ -256,10 -261,12 +256,10 @@@ 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", @@@ -271,11 -278,8 +271,11 @@@ out 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; } /** @@@ -299,7 -303,7 +299,7 @@@ * \sa send_standard_callback_request(), send_callback_request(). */ int send_option_arg_callback_request(struct osl_object *options, - int argc, char * const * const argv, callback_function *f, + int argc, char * const * const argv, afs_callback *f, callback_result_handler *result_handler, void *private_result_data) { @@@ -341,7 -345,7 +341,7 @@@ * send_option_arg_callback_request(). */ int send_standard_callback_request(int argc, char * const * const argv, - callback_function *f, callback_result_handler *result_handler, + afs_callback *f, callback_result_handler *result_handler, void *private_result_data) { return send_option_arg_callback_request(NULL, argc, argv, f, result_handler, @@@ -501,7 -505,6 +501,7 @@@ static int activate_mood_or_playlist(ch enum play_mode mode; int ret; + PARA_INFO_LOG("new playlist: %s\n", arg); if (!arg) { ret = change_current_mood(NULL); /* always successful */ mode = PLAY_MODE_MOOD; @@@ -556,70 -559,52 +556,70 @@@ int afs_cb_result_handler(struct osl_ob 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; + } } -static void com_select_callback(int fd, const struct osl_object *query) +static void flush_and_free_pb(struct para_buffer *pb) { - struct para_buffer pb = { - .max_size = shm_get_shmmax(), - .private_data = &(struct afs_max_size_handler_data) { - .fd = fd, - .band = SBD_OUTPUT - }, - .max_size_handler = afs_max_size_handler, - }; - char *arg = query->data; - int num_admissible, ret, ret2; + int ret; + struct afs_max_size_handler_data *amshd = pb->private_data; + + if (pb->buf && pb->size > 0) { + ret = pass_buffer_as_shm(amshd->fd, amshd->band, pb->buf, + pb->offset); + if (ret < 0) + PARA_ERROR_LOG("%s\n", para_strerror(-ret)); + } + free(pb->buf); +} + +static int com_select_callback(struct afs_callback_arg *aca) +{ + char *arg = aca->query.data; + int num_admissible, ret; ret = clear_score_table(); if (ret < 0) { - ret2 = para_printf(&pb, "%s\n", para_strerror(-ret)); - goto out; + para_printf(&aca->pbout, "could not clear score table: %s\n", + para_strerror(-ret)); + return ret; } if (current_play_mode == PLAY_MODE_MOOD) close_current_mood(); else playlist_close(); ret = activate_mood_or_playlist(arg, &num_admissible); - if (ret < 0) { - ret2 = para_printf(&pb, "%s\nswitching back to %s\n", - para_strerror(-ret), current_mop? - current_mop : "dummy"); - ret = activate_mood_or_playlist(current_mop, &num_admissible); - if (ret < 0) { - if (ret2 >= 0) - ret2 = para_printf(&pb, "failed, switching to dummy\n"); - activate_mood_or_playlist(NULL, &num_admissible); - } - } else - ret2 = para_printf(&pb, "activated %s (%d admissible files)\n", - current_mop? current_mop : "dummy mood", - num_admissible); + if (ret >= 0) + goto out; + /* ignore subsequent errors (but log them) */ + para_printf(&aca->pbout, "could not activate %s: %s\n" + "switching back to %s\n", + arg, para_strerror(-ret), current_mop? current_mop : "dummy"); + ret = activate_mood_or_playlist(current_mop, &num_admissible); + if (ret >= 0) + goto out; + para_printf(&aca->pbout, "could not activate %s: %s\nswitching to dummy\n", + current_mop, para_strerror(-ret)); + activate_mood_or_playlist(NULL, &num_admissible); out: - if (ret2 >= 0 && pb.offset) - pass_buffer_as_shm(fd, SBD_OUTPUT, pb.buf, pb.offset); - free(pb.buf); + para_printf(&aca->pbout, "activated %s (%d admissible files)\n", + current_mop? current_mop : "dummy mood", num_admissible); + return ret; } int com_select(struct command_context *cc) @@@ -693,7 -678,7 +693,7 @@@ static int make_database_dir(void get_database_dir(); ret = para_mkdir(database_dir, 0777); - if (ret >= 0 || is_errno(-ret, EEXIST)) + if (ret >= 0 || ret == -ERRNO_TO_PARA_ERROR(EEXIST)) return 1; return ret; } @@@ -810,8 -795,8 +810,8 @@@ int pass_buffer_as_shm(int fd, uint8_t 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; @@@ -822,8 -807,7 +822,8 @@@ 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; @@@ -836,43 -820,26 +836,43 @@@ err return ret; } -/* - * On errors, negative value is written to fd. - * On success: If query produced a result, the result_shmid is written to fd. - * Otherwise, zero is written. - */ static int call_callback(int fd, int query_shmid) { void *query_shm; struct callback_query *cq; - struct osl_object query; - int ret; + int ret, ret2; + struct afs_callback_arg aca = {.fd = fd}; ret = shm_attach(query_shmid, ATTACH_RW, &query_shm); if (ret < 0) return ret; cq = query_shm; - query.data = (char *)query_shm + sizeof(*cq); - query.size = cq->query_size; - cq->handler(fd, &query); - return shm_detach(query_shm); + aca.query.data = (char *)query_shm + sizeof(*cq); + aca.query.size = cq->query_size; + aca.pbout.max_size = shm_get_shmmax(); + aca.pbout.max_size_handler = afs_max_size_handler; + aca.pbout.private_data = &(struct afs_max_size_handler_data) { + .fd = fd, + .band = SBD_OUTPUT + }; + ret = cq->handler(&aca); + 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; + } + flush_and_free_pb(&aca.pbout); + 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) @@@ -1031,10 -998,17 +1031,10 @@@ out exit(EXIT_FAILURE); } -static void create_tables_callback(int fd, const struct osl_object *query) +static int com_init_callback(struct afs_callback_arg *aca) { - uint32_t table_mask = *(uint32_t *)query->data; + uint32_t table_mask = *(uint32_t *)aca->query.data; int i, ret; - struct para_buffer pb = { - .max_size = shm_get_shmmax(), - .private_data = &(struct afs_max_size_handler_data) { - .fd = fd, - .band = SBD_OUTPUT - } - }; close_afs_tables(); for (i = 0; i < NUM_AFS_TABLES; i++) { @@@ -1045,19 -1019,17 +1045,19 @@@ if (!t->create) continue; ret = t->create(database_dir); - if (ret < 0) + if (ret < 0) { + para_printf(&aca->pbout, "cannot create table %s\n", + t->name); goto out; - para_printf(&pb, "successfully created %s table\n", t->name); + } + para_printf(&aca->pbout, "successfully created %s table\n", + t->name); } ret = open_afs_tables(); -out: if (ret < 0) - para_printf(&pb, "%s\n", para_strerror(-ret)); - if (pb.buf) - pass_buffer_as_shm(fd, SBD_OUTPUT, pb.buf, pb.offset); - free(pb.buf); + para_printf(&aca->pbout, "cannot open afs tables\n"); +out: + return ret; } int com_init(struct command_context *cc) @@@ -1085,8 -1057,9 +1085,8 @@@ return -E_BAD_TABLE_NAME; } } - ret = send_callback_request(create_tables_callback, &query, + return send_callback_request(com_init_callback, &query, afs_cb_result_handler, cc); - return ret; } /** @@@ -1100,9 -1073,7 +1100,9 @@@ enum com_check_flags /** Check the mood table. */ CHECK_MOODS = 2, /** Check the playlist table. */ - CHECK_PLAYLISTS = 4 + CHECK_PLAYLISTS = 4, + /** Check the attribute table against the audio file table. */ + CHECK_ATTS = 8 }; int com_check(struct command_context *cc) @@@ -1122,10 -1093,6 +1122,10 @@@ flags |= CHECK_AFT; continue; } + if (!strcmp(arg, "-A")) { + flags |= CHECK_ATTS; + continue; + } if (!strcmp(arg, "-p")) { flags |= CHECK_PLAYLISTS; continue; @@@ -1146,12 -1113,6 +1146,12 @@@ if (ret < 0) return ret; } + if (flags & CHECK_ATTS) { + ret = send_callback_request(attribute_check_callback, NULL, + afs_cb_result_handler, cc); + if (ret < 0) + return ret; + } if (flags & CHECK_PLAYLISTS) { ret = send_callback_request(playlist_check_callback, NULL, afs_cb_result_handler, cc); @@@ -1174,14 -1135,10 +1174,14 @@@ * \param pb May be \p NULL. * \param data Type depends on \a event. * - * This function calls the table handlers of all tables and passes \a pb and \a - * data verbatim. It's up to the handlers to interpret the \a data pointer. + * This function calls each table event handler, passing \a pb and \a data + * verbatim. It's up to the handlers to interpret the \a data pointer. If a + * handler returns negative, the loop is aborted. + * + * \return The (negative) error code of the first handler that failed, or non-negative + * if all handlers succeeded. */ -void afs_event(enum afs_events event, struct para_buffer *pb, +__must_check int afs_event(enum afs_events event, struct para_buffer *pb, void *data) { int i, ret; @@@ -1191,13 -1148,10 +1191,13 @@@ if (!t->event_handler) continue; ret = t->event_handler(event, pb, data); - if (ret < 0) + if (ret < 0) { PARA_CRIT_LOG("table %s, event %d: %s\n", t->name, event, para_strerror(-ret)); + return ret; + } } + return 1; } /** diff --combined error.h index 5d5666c6,49a57a5a..40e097e3 --- a/error.h +++ b/error.h @@@ -279,7 -279,6 +279,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_MATCH, "no matches"), \ #define USER_LIST_ERRORS \ @@@ -579,20 -578,8 +579,8 @@@ /** Set the osl error bit for the given number. */ #define OSL_ERRNO_TO_PARA_ERROR(num) ((num) | (1 << OSL_ERROR_BIT)) - /** Check whether a given number is a system error number. - * - * \param num The value to be checked. - * \param _errno The system error number. - * - * \return True if \a num is paraslash's representation of the system - * error identified by \a _errno. - */ - _static_inline_ bool is_errno(int num, int _errno) - { - assert(num > 0 && _errno > 0); - return ERRNO_TO_PARA_ERROR(_errno) == num; - } + static const char *weak_osl_strerror(int) __attribute__ ((weakref("osl_strerror"))); /** * Paraslash's version of strerror(3). * @@@ -603,12 -590,12 +591,12 @@@ _static_inline_ const char *para_strerror(int num) { assert(num > 0); - #ifdef _OSL_H - if (IS_OSL_ERROR(num)) - return osl_strerror(num & ((1 << OSL_ERROR_BIT) - 1)); - #endif + if (IS_OSL_ERROR(num)) { + assert(weak_osl_strerror); + return weak_osl_strerror(num & ~(1U << OSL_ERROR_BIT)); + } if (IS_SYSTEM_ERROR(num)) - return strerror(num & ((1 << SYSTEM_ERROR_BIT) - 1)); + return strerror(num & ~(1U << SYSTEM_ERROR_BIT)); return para_errlist[ERRNUM_TO_SS(num)][ERRNUM_TO_INDEX(num)]; }