]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
Allow global at exit init functions to return error codes
authorArran Cudbard-Bell <a.cudbardb@freeradius.org>
Thu, 12 Jan 2023 19:06:20 +0000 (13:06 -0600)
committerArran Cudbard-Bell <a.cudbardb@freeradius.org>
Thu, 12 Jan 2023 19:06:20 +0000 (13:06 -0600)
src/lib/server/module.c
src/lib/util/atexit.h
src/lib/util/event.c
src/lib/util/regex.c

index 237689ec2f02dffd71685a83c8f72c583396bd1a..c0bf9391247ded6bda36f219da60830a4a4b26a6 100644 (file)
@@ -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));
 }
index 5cc22a7e96fb1caea6c3bbfe91d1960267f687d6..0ca76790c1a52f71cec7f3785c8f93324bcbaf49 100644 (file)
@@ -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
  *
index 26a7cbb3f8a1cb5087c0c7b2ac9cc9a12b59031d..8afdf5b2e7571e8a3a53dbb2129a47f4394f0a06 100644 (file)
@@ -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)) {
index 6afe60b07eb6e780b034a4e7e9dfeec541e5dfd1..2807b0f4a1639eaf36df7c6d8f4898d6e81e378a 100644 (file)
@@ -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;