From: Arran Cudbard-Bell Date: Thu, 12 Jan 2023 19:06:20 +0000 (-0600) Subject: Allow global at exit init functions to return error codes X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b00c446b7071d29ba9563d4df556ea235fe223b3;p=thirdparty%2Ffreeradius-server.git Allow global at exit init functions to return error codes --- diff --git a/src/lib/server/module.c b/src/lib/server/module.c index 237689ec2f0..c0bf9391247 100644 --- a/src/lib/server/module.c +++ b/src/lib/server/module.c @@ -1102,7 +1102,7 @@ module_list_t *module_list_alloc(TALLOC_CTX *ctx, char const *name) return ml; } -static void _module_global_list_init(void *uctx) +static int _module_global_list_init(void *uctx) { dl_modules = dl_module_loader_init(uctx); MEM(module_global_inst_list = fr_heap_alloc(NULL, _module_instance_global_cmp, module_instance_t, inst_idx, 256)); @@ -1112,6 +1112,8 @@ static void _module_global_list_init(void *uctx) * tree is in place... */ global_lib_init(); + + return 0; } static int _module_global_list_free(UNUSED void *uctx) @@ -1133,10 +1135,11 @@ static int _module_global_list_free(UNUSED void *uctx) */ void modules_init(char const *lib_dir) { + int ret; /* * Create the global module heap we use for * common indexes in the thread-specific * heaps. */ - fr_atexit_global_once(_module_global_list_init, _module_global_list_free, UNCONST(char *, lib_dir)); + fr_atexit_global_once(NULL, _module_global_list_init, _module_global_list_free, UNCONST(char *, lib_dir)); } diff --git a/src/lib/util/atexit.h b/src/lib/util/atexit.h index 5cc22a7e96f..0ca76790c1a 100644 --- a/src/lib/util/atexit.h +++ b/src/lib/util/atexit.h @@ -82,12 +82,16 @@ bool fr_atexit_is_exiting(void); * * ...when functions are tested directly in the fr_atexit_global_once macro */ -static inline void _fr_atexit_global_once_funcs(fr_atexit_t init_func, fr_atexit_t free_func, void *uctx) +static inline int _fr_atexit_global_once_funcs(fr_atexit_t init_func, fr_atexit_t free_func, void *uctx) { - if (init_func) init_func(uctx); - if (free_func) free_func(uctx); + if (init_func) if (init_func(uctx) < 0) return -1; + if (free_func) fr_atexit_global(free_func, uctx); + + return 0; } +static inline void fr_atexit_noop(void) {} + /** Setup pair of global init/free functions * * Simplifies setting up data structures the first time a given function @@ -98,6 +102,9 @@ static inline void _fr_atexit_global_once_funcs(fr_atexit_t init_func, fr_atexit * * Will not share init status outside of the function. * + * @param[out] _res Where to write the result of the init + * function if called. + * May be NULL. * @param[in] _init function to call. Will be called once * during the process lifetime. * May be NULL. @@ -106,7 +113,7 @@ static inline void _fr_atexit_global_once_funcs(fr_atexit_t init_func, fr_atexit * May be NULL. * @param[in] _uctx data to be passed to free function. */ -#define fr_atexit_global_once(_init, _free, _uctx) \ +#define fr_atexit_global_once(_res, _init, _free, _uctx) \ { \ static atomic_bool _init_done = false; \ static pthread_mutex_t _init_mutex = PTHREAD_MUTEX_INITIALIZER; \ @@ -114,11 +121,15 @@ static inline void _fr_atexit_global_once_funcs(fr_atexit_t init_func, fr_atexit if (unlikely(!atomic_load(&_init_done))) { \ pthread_mutex_lock(&_init_mutex); \ if (!atomic_load(&_init_done)) { \ - _fr_atexit_global_once_funcs(_init, _free, _our_uctx); \ + if (_fr_atexit_global_once_funcs(_init, _free, _our_uctx) < 0) { \ + _Generic((_res), int : _res = -1, default: fr_atexit_noop()); \ + pthread_mutex_unlock(&_init_mutex); \ + } \ atomic_store(&_init_done, true); \ } \ pthread_mutex_unlock(&_init_mutex); \ } \ + _Generic((_res), int : _res = 0, default: fr_atexit_noop()); \ } /** Set a destructor for thread local storage to free the memory on thread exit * diff --git a/src/lib/util/event.c b/src/lib/util/event.c index 26a7cbb3f8a..8afdf5b2e75 100644 --- a/src/lib/util/event.c +++ b/src/lib/util/event.c @@ -1758,7 +1758,7 @@ int _fr_event_pid_wait(NDEBUG_LOCATION_ARGS fr_strerror_clear(); ev->is_registered = false; - + /* * If the child exited before kevent() was * called, we need to get its status via @@ -1808,7 +1808,7 @@ int _fr_event_pid_wait(NDEBUG_LOCATION_ARGS /* * The user event acts as a surrogate for - * an EVFILT_PROC event, and will be evaluated + * an EVFILT_PROC event, and will be evaluated * during the next loop through the event loop. * * It will be automatically deleted when the @@ -1818,7 +1818,7 @@ int _fr_event_pid_wait(NDEBUG_LOCATION_ARGS * callback here directly, but this lead to * multiple problems, the biggest being that * setting requests back to resumable failed - * because they were not yet yielded, + * because they were not yet yielded, * leading to hangs. */ if (fr_event_user_insert(ev, el, &ev->early_exit.ev, true, _fr_event_pid_early_exit, ev) < 0) { @@ -2132,7 +2132,7 @@ void event_user_eval(fr_event_list_t *el, struct kevent *kev) * - 0 on success. * - -1 on error. */ -int _fr_event_user_insert(NDEBUG_LOCATION_ARGS +int _fr_event_user_insert(NDEBUG_LOCATION_ARGS TALLOC_CTX *ctx, fr_event_list_t *el, fr_event_user_t **ev_p, bool trigger, fr_event_user_cb_t callback, void *uctx) { @@ -2764,11 +2764,12 @@ static int _event_free_indexes(UNUSED void *uctx) return 0; } -static void _event_build_indexes(UNUSED void *uctx) +static int _event_build_indexes(UNUSED void *uctx) { unsigned int i; for (i = 0; i < NUM_ELEMENTS(filter_maps); i++) event_fd_func_index_build(&filter_maps[i]); + return 0; } /** Initialise a new event list @@ -2784,12 +2785,14 @@ fr_event_list_t *fr_event_list_alloc(TALLOC_CTX *ctx, fr_event_status_cb_t statu { fr_event_list_t *el; struct kevent kev; + int ret; /* * Build the map indexes the first time this * function is called. */ - fr_atexit_global_once(_event_build_indexes, _event_free_indexes, NULL); + fr_atexit_global_once(ret, _event_build_indexes, _event_free_indexes, NULL); + if (unlikely(ret < 0)) return NULL; el = talloc_zero(ctx, fr_event_list_t); if (!fr_cond_assert(el)) { diff --git a/src/lib/util/regex.c b/src/lib/util/regex.c index 6afe60b07eb..2807b0f4a16 100644 --- a/src/lib/util/regex.c +++ b/src/lib/util/regex.c @@ -674,7 +674,7 @@ static int _pcre_globals_reset(UNUSED void *uctx) return 0; } -static void _pcre_globals_configure(UNUSED void *uctx) +static int _pcre_globals_configure(UNUSED void *uctx) { #ifdef PCRE_CONFIG_JIT int *do_jit = 0; @@ -691,6 +691,8 @@ static void _pcre_globals_configure(UNUSED void *uctx) #endif pcre_malloc = _pcre_talloc; /* pcre_malloc is a global provided by libpcre */ pcre_free = _pcre_talloc_free; /* pcre_free is a global provided by libpcre */ + + return 0; } /** Free thread local data @@ -783,9 +785,12 @@ ssize_t regex_compile(TALLOC_CTX *ctx, regex_t **out, char const *pattern, size_ char const *error; int offset; int cflags = 0; + int ret; regex_t *preg; - fr_atexit_global_once(_pcre_globals_configure, _pcre_globals_reset, NULL); + fr_atexit_global_once(ret, _pcre_globals_configure, _pcre_globals_reset, NULL); + if (unlikely(ret < 0)) return -1; + if (unlikely(pcre_tls_init() < 0)) return -1;