From: Daniel Kolesa Date: Fri, 16 Mar 2018 14:41:24 +0000 (+0100) Subject: eolian: initial API for a new panic mechanism X-Git-Tag: upstream/1.21.0~1606 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=ca3ab59e72f72d66c1da24f69a6beafa06a47c15;p=platform%2Fupstream%2Fefl.git eolian: initial API for a new panic mechanism This will be used to handle unrecoverable errors. For robustness, you will be able to set a custom panic callback, jump and try to recover manually. --- diff --git a/src/lib/eolian/Eolian.h b/src/lib/eolian/Eolian.h index 370c334..54300cf 100644 --- a/src/lib/eolian/Eolian.h +++ b/src/lib/eolian/Eolian.h @@ -200,6 +200,8 @@ typedef struct _Eolian_Unit Eolian_Unit; #define EOLIAN_OBJECT(expr) EOLIAN_CAST(Eolian_Object, expr) #define EOLIAN_UNIT(expr) EOLIAN_CAST(Eolian_Unit, expr) +typedef void (*Eolian_Panic_Cb)(const Eolian_State *state, Eina_Stringshare *msg); + typedef enum { EOLIAN_OBJECT_UNKNOWN = 0, @@ -487,6 +489,11 @@ EAPI int eolian_shutdown(void); * * You need to free this with eolian_free once you're done. * + * This will assign a default panic function, which printers the error + * message passed to it into the standard Eolian log. + * + * @see eolian_panic_cb_set + * * @return A new state (or NULL on failure). * * @ingroup Eolian @@ -494,6 +501,29 @@ EAPI int eolian_shutdown(void); EAPI Eolian_State *eolian_state_new(void); /* + * @brief Set the panic function for the state. + * + * When an unrecoverable error happens in an Eolian API call, the panic + * function is called. The default panic function for a state just prints + * the error message into the standard Eolian log. After the panic function + * is called, Eolian forcibly exits (`exit(EXIT_FAILURE)`). If you don't + * want this, you can override the panic function and never return from + * it (by doing a long jump, or throwing an exception in C++). + * + * Unrecoverable errors include cases such as internal errors and memory + * allocation failures. Standard parse errors etc. are not considered + * unrecoverable, so they are not handled using the panic mechanism. + * + * After a panic, the Eolian state is left valid; the library does its + * best at trying to provide it back to you in the same condition as it + * was before the failing call. + * + * If you set a panic function and jump, you're responsible for the error + * message and have to delete it with eina_stringshare_del. + */ +EAPI Eolian_Panic_Cb eolian_panic_cb_set(Eolian_State *state, Eolian_Panic_Cb cb); + +/* * @brief Free an Eolian state. * * You can use this to free an Eolian state. diff --git a/src/lib/eolian/eolian_database.c b/src/lib/eolian/eolian_database.c index 7300d46..70fe7a8 100644 --- a/src/lib/eolian/eolian_database.c +++ b/src/lib/eolian/eolian_database.c @@ -564,6 +564,12 @@ _hashlist_free(void *data) eina_list_free((Eina_List*)data); } +static void +_default_panic_cb(const Eolian_State *state EINA_UNUSED, const char *msg) +{ + _eolian_log(msg); +} + EAPI Eolian_State * eolian_state_new(void) { @@ -571,6 +577,15 @@ eolian_state_new(void) if (!state) return NULL; + state->panic = _default_panic_cb; + + if (setjmp(state->jmp_env)) + { + state->panic(state, state->panic_msg); + eina_stringshare_del(state->panic_msg); + exit(EXIT_FAILURE); + } + database_unit_init(state, &state->unit, NULL); state->filenames_eo = eina_hash_string_small_new(free); diff --git a/src/lib/eolian/eolian_database.h b/src/lib/eolian/eolian_database.h index 28ff787..813f3f5 100644 --- a/src/lib/eolian/eolian_database.h +++ b/src/lib/eolian/eolian_database.h @@ -1,6 +1,8 @@ #ifndef __EOLIAN_DATABASE_H #define __EOLIAN_DATABASE_H +#include + #include extern int _eolian_log_dom; @@ -49,6 +51,10 @@ struct _Eolian_State { Eolian_Unit unit; + Eolian_Panic_Cb panic; + Eina_Stringshare *panic_msg; + jmp_buf jmp_env; + Eina_Hash *filenames_eo; /* filename to full path mapping */ Eina_Hash *filenames_eot;