fr_dhcpv4_global_free();
fr_dict_autofree(dhcpclient_dict);
- return ret < 0 ? 1 : 0;
+ /*
+ * Ensure our atexit handlers run before any other
+ * atexit handlers registered by third party libraries.
+ */
+ fr_atexit_global_trigger_all();
+
+ return ret < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
}
static dl_loader_t *dl_loader;
static fr_dict_t *dict = NULL;
-static fr_dict_gctx_t const *dict_gctx = NULL;
int LLVMFuzzerInitialize(int *argc, char ***argv);
int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len);
{
fr_dict_free(&dict, __FILE__);
- if (fr_dict_global_ctx_free(dict_gctx) < 0) fr_perror("fuzzer");
-
if (dl && dl->handle) {
dlclose(dl->handle);
dl->handle = NULL;
}
talloc_free(dl_loader);
+
+ /*
+ * Ensure our atexit handlers run before any other
+ * atexit handlers registered by third party libraries.
+ */
+ fr_atexit_global_trigger_all();
}
int LLVMFuzzerInitialize(int *argc, char ***argv)
fr_exit_now(EXIT_FAILURE);
}
- dict_gctx = fr_dict_global_ctx_init(NULL, true, dict_dir);
- if (!dict_gctx) {
+ if (!fr_dict_global_ctx_init(NULL, true, dict_dir)) {
fr_perror("dict_global");
fr_exit_now(EXIT_FAILURE);
}
);
}
- if ((stats.lost > 0) || (stats.failed > 0)) {
- fr_exit_now(EXIT_FAILURE);
- }
+ /*
+ * Ensure our atexit handlers run before any other
+ * atexit handlers registered by third party libraries.
+ */
+ fr_atexit_global_trigger_all();
- fr_exit_now(EXIT_SUCCESS);
+ if ((stats.lost > 0) || (stats.failed > 0)) return EXIT_FAILURE;
+
+ return EXIT_SUCCESS;
}
char const *protocol = NULL;
TALLOC_CTX *autofree;
- fr_dict_gctx_t const *our_dict_gctx = NULL;
/*
* Must be called first, so the handler is called last
goto finish;
}
- our_dict_gctx = fr_dict_global_ctx_init(NULL, true, dict_dir);
- if (!our_dict_gctx) {
+ if (!fr_dict_global_ctx_init(NULL, true, dict_dir)) {
fr_perror("radict");
ret = 1;
goto finish;
fr_dict_free(dict_p, __FILE__);
} while (++dict_p < dict_end);
}
- if (fr_dict_global_ctx_free(our_dict_gctx) < 0) fr_perror("radict");
if (talloc_free(autofree) < 0) fr_perror("radict");
+
+ /*
+ * Ensure our atexit handlers run before any other
+ * atexit handlers registered by third party libraries.
+ */
+ fr_atexit_global_trigger_all();
+
return found ? ret : 64;
}
if (!rad_suid_is_down_permanent() && (fr_get_lsan_state() == 1)) rad_suid_up();
fr_strerror_clear(); /* clear error buffer */
+ /*
+ * Ensure our atexit handlers run before any other
+ * atexit handlers registered by third party libraries.
+ */
+ fr_atexit_global_trigger_all();
+
return ret;
}
char const *raddb_dir = RADDBDIR;
char const *dict_dir = DICTDIR;
TALLOC_CTX *autofree;
- fr_dict_gctx_t const *dict_gctx = NULL;
rs_stats_t *stats;
conf->pcap_filter, conf->pcap_filter);
}
- dict_gctx = fr_dict_global_ctx_init(NULL, true, dict_dir);
- if (!dict_gctx) {
+ if (!fr_dict_global_ctx_init(NULL, true, dict_dir)) {
fr_perror("radsniff");
fr_exit_now(EXIT_FAILURE);
}
fr_dict_autofree(radsniff_dict);
fr_radius_free();
- if (fr_dict_global_ctx_free(dict_gctx) < 0) {
- fr_perror("radsniff");
- ret = EXIT_FAILURE;
- }
+ /*
+ * Ensure our atexit handlers run before any other
+ * atexit handlers registered by third party libraries.
+ */
+ fr_atexit_global_trigger_all();
return ret;
}
*/
fr_dict_autofree(radsnmp_dict);
+ /*
+ * Ensure our atexit handlers run before any other
+ * atexit handlers registered by third party libraries.
+ */
+ fr_atexit_global_trigger_all();
+
return ret;
}
int zap = 0;
fr_dict_t *dict = NULL;
TALLOC_CTX *autofree;
- fr_dict_gctx_t const *dict_gctx = NULL;
char const *p;
main_config_t *config;
return 1;
}
- dict_gctx = fr_dict_global_ctx_init(NULL, true, config->dict_dir);
- if (!dict_gctx) {
+ if (!fr_dict_global_ctx_init(NULL, true, config->dict_dir)) {
fr_perror("%s", main_config->name);
fr_exit_now(EXIT_FAILURE);
}
}
fclose(fp);
- if (fr_dict_global_ctx_free(dict_gctx) < 0) {
- fr_perror("radwho");
- ret = EXIT_FAILURE;
- }
main_config_free(&config);
+ /*
+ * Ensure our atexit handlers run before any other
+ * atexit handlers registered by third party libraries.
+ */
+ fr_atexit_global_trigger_all();
+
return ret;
}
ret = EXIT_FAILURE;
}
+ /*
+ * Ensure our atexit handlers run before any other
+ * atexit handlers registered by third party libraries.
+ */
+ fr_atexit_global_trigger_all();
+
return ret;
}
};
map_list_init(&list);
- /*
- * Must be called first, so the handler is called last
- */
- fr_atexit_global_setup();
config = main_config_alloc(NULL);
if (!config) {
char const *receipt_file = NULL;
TALLOC_CTX *autofree;
- fr_dict_gctx_t const *dict_gctx = NULL;
/*
* Must be called first, so the handler is called last
EXIT_WITH_FAILURE;
}
- dict_gctx = fr_dict_global_ctx_init(NULL, true, dict_dir);
- if (!dict_gctx) {
+ if (!fr_dict_global_ctx_init(NULL, true, dict_dir)) {
fr_perror("unit_test_map");
EXIT_WITH_FAILURE;
}
ret = EXIT_FAILURE;
}
- if (fr_dict_global_ctx_free(dict_gctx) < 0) {
- fr_perror("unit_test_map");
- ret = EXIT_FAILURE;
- }
-
if (receipt_file && (ret == EXIT_SUCCESS) && (fr_touch(NULL, receipt_file, 0644, true, 0755) <= 0)) {
fr_perror("unit_test_map");
ret = EXIT_FAILURE;
}
+ /*
+ * Ensure our atexit handlers run before any other
+ * atexit handlers registered by third party libraries.
+ */
+ fr_atexit_global_trigger_all();
+
return ret;
}
char const *receipt_file = NULL;
TALLOC_CTX *autofree;
- fr_dict_gctx_t const *dict_gctx = NULL;
TALLOC_CTX *thread_ctx;
char *p;
*/
modules_init(config->lib_dir);
- dict_gctx = fr_dict_global_ctx_init(NULL, true, config->dict_dir);
- if (!dict_gctx) {
+ if (!fr_dict_global_ctx_init(NULL, true, config->dict_dir)) {
fr_perror("%s", config->name);
EXIT_WITH_FAILURE;
}
ret = EXIT_FAILURE;
}
+ /*
+ * Ensure our atexit handlers run before any other
+ * atexit handlers registered by third party libraries.
+ */
+ fr_atexit_global_trigger_all();
+
return ret;
}
}
}
+/** Cause all thread local free triggers to fire
+ *
+ * This is necessary when we're running in single threaded mode
+ * to ensure all "thread-local" memory (which isn't actually thread local)
+ * is cleaned up.
+ *
+ * One example is the OpenSSL log BIOs which must be cleaned up
+ * before fr_openssl_free is called.
+ */
+unsigned int fr_atexit_thread_trigger_all(void)
+{
+ fr_atexit_entry_t *e = NULL, *ee;
+ fr_atexit_list_t *list;
+ unsigned int count = 0;
+
+ /*
+ * Iterate over the list of thread local
+ * destructor lists running the
+ * destructors.
+ */
+ while ((e = fr_dlist_next(&fr_atexit_threads->head, e))) {
+ if (!e->func) continue; /* thread already joined */
+
+ list = talloc_get_type_abort(e->uctx, fr_atexit_list_t);
+ ee = NULL;
+ while ((ee = fr_dlist_next(&list->head, ee))) {
+ ATEXIT_DEBUG("%s - Thread %u triggering %p/%p func=%p, uctx=%p (alloced %s:%u)",
+ __FUNCTION__,
+ (unsigned int)pthread_self(),
+ list, ee, ee->func, ee->uctx, ee->file, ee->line);
+
+ count++;
+ ee = fr_dlist_talloc_free_item(&list->head, ee);
+ }
+ }
+
+ return count;
+}
+
/** Remove a specific global destructor (without executing it)
*
* @note This function's primary purpose is to help diagnose issues with destructors
}
}
+/** Cause all global free triggers to fire
+ *
+ * This is necessary when libraries (perl) register their own
+ * atexit handlers using the normal POSIX mechanism, and we need
+ * to ensure all our atexit handlers fire before so any global
+ * deinit is done explicitly by us.
+ */
+unsigned int fr_atexit_global_trigger_all(void)
+{
+ fr_atexit_entry_t *e = NULL;
+ unsigned int count = 0;
+
+ /*
+ * Iterate over the list of thread local
+ * destructor lists running the
+ * destructors.
+ */
+ while ((e = fr_dlist_next(&fr_atexit_global->head, e))) {
+ ATEXIT_DEBUG("%s - Triggering %p/%p func=%p, uctx=%p (alloced %s:%u)",
+ __FUNCTION__,
+ fr_atexit_global, e, e->func, e->uctx, e->file, e->line);
+
+ count++;
+ e = fr_dlist_talloc_free_item(&fr_atexit_global->head, e);
+ }
+
+ return count;
+}
+
/** Iterates through all thread local destructor lists, causing destructor to be triggered
*
* This should only be called by the main process not by threads.
return count;
}
-/** Cause all thread local free triggers to fire
- *
- * This is necessary when we're running in single threaded mode
- * to ensure all "thread-local" memory (which isn't actually thread local)
- * is cleaned up.
- *
- * One example is the OpenSSL log BIOs which must be cleaned up
- * before fr_openssl_free is called.
- */
-unsigned int fr_atexit_thread_trigger_all(void)
-{
- fr_atexit_entry_t *e = NULL, *ee;
- fr_atexit_list_t *list;
- unsigned int count = 0;
-
- /*
- * Iterate over the list of thread local
- * destructor lists running the
- * destructors.
- */
- while ((e = fr_dlist_next(&fr_atexit_threads->head, e))) {
- if (!e->func) continue; /* thread already joined */
-
- list = talloc_get_type_abort(e->uctx, fr_atexit_list_t);
- ee = NULL;
- while ((ee = fr_dlist_next(&list->head, ee))) {
- ATEXIT_DEBUG("%s - Thread %u triggering %p/%p func=%p, uctx=%p (alloced %s:%u)",
- __FUNCTION__,
- (unsigned int)pthread_self(),
- list, ee, ee->func, ee->uctx, ee->file, ee->line);
-
- count++;
- ee = fr_dlist_talloc_free_item(&list->head, ee);
- }
- }
-
- return count;
-}
/** Return whether we're currently in the teardown phase
*
void fr_atexit_thread_local_disarm_all(void);
+unsigned int fr_atexit_thread_trigger_all(void);
+
unsigned int fr_atexit_global_disarm(bool uctx_scope, fr_atexit_t func, void const *uctx);
void fr_atexit_global_disarm_all(void);
-unsigned int fr_atexit_trigger(bool uctx_scope, fr_atexit_t func, void const *uctx);
+unsigned int fr_atexit_global_trigger_all(void);
-unsigned int fr_atexit_thread_trigger_all(void);
+unsigned int fr_atexit_trigger(bool uctx_scope, fr_atexit_t func, void const *uctx);
bool fr_atexit_is_exiting(void);
#endif
TALLOC_CTX *autofree;
- fr_dict_gctx_t const *dict_gctx = NULL;
char *commands[MAX_COMMANDS];
int num_commands = -1;
* Need to read in the dictionaries, else we may get
* validation errors when we try and parse the config.
*/
- dict_gctx = fr_dict_global_ctx_init(NULL, true, dict_dir);
- if (!dict_gctx) {
+ if (!fr_dict_global_ctx_init(NULL, true, dict_dir)) {
fr_perror("radmin");
fr_exit_now(64);
}
exit:
fr_dict_free(&dict, __FILE__);
- if (fr_dict_global_ctx_free(dict_gctx) < 0) fr_perror("radmin");
-
if (inputfp != stdin) fclose(inputfp);
if (radmin_log.dst == L_DST_FILES) close(radmin_log.fd);
if (!quiet) fprintf(stdout, "\n");
+ /*
+ * Ensure our atexit handlers run before any other
+ * atexit handlers registered by third party libraries.
+ */
+ fr_atexit_global_trigger_all();
+
return exit_status;
}
User-Password = "hello"
Password.Cleartext = "hello"
Received Accounting-Response Id 123 from 127.0.0.1:12340 to 0.0.0.0:1234 via lo length 20
+(0) src/tests/radclient/acct_1.txt response code 5
User-Password = "hello"
Password.Cleartext = "hello"
Received Access-Accept Id 123 from 127.0.0.1:12340 to 0.0.0.0:1234 via lo length 20
+(0) src/tests/radclient/auth_1.txt response code 2
Class = 0x483d342c493d34
raw.Vendor-Specific = 0x483d342c493d34
raw.Vendor-Specific = 0x483d342c493d43
+(0) src/tests/radclient/auth_4.txt response code 2