]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
- auth-load-thread, implement active thread counter for auth load threads. auth-load-thread
authorW.C.A. Wijngaards <wouter@nlnetlabs.nl>
Tue, 7 Jul 2026 15:21:16 +0000 (17:21 +0200)
committerW.C.A. Wijngaards <wouter@nlnetlabs.nl>
Tue, 7 Jul 2026 15:21:16 +0000 (17:21 +0200)
daemon/daemon.c
daemon/daemon.h
services/authload.c
services/authload.h
services/authzone.c

index 80cb37ff755f33cf89f5589eb0eb852c2ac2339c..aa90535f7315b287ea84c3c876c9dd3d0a2033d9 100644 (file)
@@ -85,6 +85,7 @@
 #include "services/view.h"
 #include "services/modstack.h"
 #include "services/authzone.h"
+#include "services/authload.h"
 #include "util/module.h"
 #include "util/random.h"
 #include "util/tube.h"
@@ -589,6 +590,17 @@ daemon_init(void)
                free(daemon);
                return NULL;
        }
+       if(!(daemon->auth_load_info = auth_load_info_create())) {
+               edns_strings_delete(daemon->env->edns_strings);
+               auth_zones_delete(daemon->env->auth_zones);
+               acl_list_delete(daemon->acl_interface);
+               acl_list_delete(daemon->acl);
+               tcl_list_delete(daemon->tcl);
+               edns_known_options_delete(daemon->env);
+               free(daemon->env);
+               free(daemon);
+               return NULL;
+       }
        return daemon;  
 }
 
@@ -1258,6 +1270,7 @@ daemon_delete(struct daemon* daemon)
                edns_strings_delete(daemon->env->edns_strings);
                auth_zones_delete(daemon->env->auth_zones);
        }
+       auth_load_info_delete(daemon->auth_load_info);
        ub_randfree(daemon->rand);
        alloc_clear(&daemon->superalloc);
        acl_list_delete(daemon->acl);
index 20386d7fc9a0a3dc29501e1e1e564540c6713cd7..9965ed558f10c330b8c7a711fe8bfa44a883af33 100644 (file)
@@ -62,6 +62,7 @@ struct doq_table;
 struct cookie_secrets;
 struct fast_reload_thread;
 struct fast_reload_printq;
+struct auth_load_general_info;
 
 #include "dnstap/dnstap_config.h"
 #ifdef USE_DNSTAP
@@ -188,6 +189,8 @@ struct daemon {
        int fast_reload_tcl_has_changes;
        /** config file name */
        char* cfgfile;
+       /** Auth load threads, the number of active threads. */
+       struct auth_load_general_info* auth_load_info;
 };
 
 /**
index 6ce62853beb44c442b008b0cf939aaebbd1318f2..01ccd94303fd8deb57b83a1d836d48d7a97383ff 100644 (file)
@@ -672,7 +672,7 @@ worker_auth_load_service_cb(int ATTR_UNUSED(fd), short ATTR_UNUSED(bits),
        ssize_t ret;
        struct auth_xfer* xfr;
        struct auth_chunk* chunk_list;
-       struct module_env* env;
+       struct module_env* env = &thr->task->worker->env;
        int ixfr_fail;
 
        log_assert(thr->commpair[0] >= 0);
@@ -719,11 +719,11 @@ worker_auth_load_service_cb(int ATTR_UNUSED(fd), short ATTR_UNUSED(bits),
                lock_rw_unlock(&thr->task->worker->env.auth_zones->lock);
                verbose(VERB_ALGO, "auth load: xfr is gone");
                auth_load_thread_delete(thr);
+               auth_load_info_release_thread(env);
                return;
        }
        lock_basic_lock(&xfr->lock);
        lock_rw_unlock(&thr->task->worker->env.auth_zones->lock);
-       env = &thr->task->worker->env;
        ixfr_fail = thr->task->ixfr_fail;
        if(thr->task->on_http) {
                chunk_list = thr->task->chunks_first;
@@ -734,6 +734,7 @@ worker_auth_load_service_cb(int ATTR_UNUSED(fd), short ATTR_UNUSED(bits),
                chunk_list = NULL;
        }
        auth_load_thread_delete(thr);
+       auth_load_info_release_thread(env);
        xfr_process_load_end_transfer(xfr, env, recv_item, ixfr_fail,
                chunk_list);
 }
@@ -815,3 +816,56 @@ int auth_load_add_task_xfr(struct auth_xfer* xfr, struct worker* worker)
        /* Make wait item */
        return 0;
 }
+
+struct auth_load_general_info* auth_load_info_create(void)
+{
+       struct auth_load_general_info* auth_load_info =
+               (struct auth_load_general_info*)calloc(1,
+                       sizeof(*auth_load_info));
+       if(!auth_load_info) {
+               log_err("malloc failure");
+               return NULL;
+       }
+       lock_basic_init(&auth_load_info->lock);
+       lock_protect(&auth_load_info->lock,
+               &auth_load_info->num_auth_load_threads,
+               sizeof(auth_load_info->num_auth_load_threads));
+       return auth_load_info;
+}
+
+void auth_load_info_delete(struct auth_load_general_info* auth_load_info)
+{
+       if(!auth_load_info)
+               return;
+       lock_basic_destroy(&auth_load_info->lock);
+       free(auth_load_info);
+}
+
+int auth_load_info_grab_thread(struct module_env* env)
+{
+       struct auth_load_general_info* auth_load_info =
+               env->worker->daemon->auth_load_info;
+       struct config_file* cfg = env->cfg;
+       int ret = 0;
+       lock_basic_lock(&auth_load_info->lock);
+       if(auth_load_info->num_auth_load_threads < cfg->auth_task_threads) {
+               ret = 1;
+               auth_load_info->num_auth_load_threads++;
+       }
+       lock_basic_unlock(&auth_load_info->lock);
+       return ret;
+}
+
+void auth_load_info_release_thread(struct module_env* env)
+{
+       struct auth_load_general_info* auth_load_info =
+               env->worker->daemon->auth_load_info;
+       lock_basic_lock(&auth_load_info->lock);
+       if(auth_load_info->num_auth_load_threads == 0) {
+               verbose(VERB_ALGO, "release of auth load thread, but "
+                       "num_auth_load_threads not > 0.");
+       } else {
+               auth_load_info->num_auth_load_threads--;
+       }
+       lock_basic_unlock(&auth_load_info->lock);
+}
index 7b884f933f0c93f7bd70dc1b4df8b683e33f04cd..718cb5d0d55417281b2cbaec042179f89f5d19bf 100644 (file)
@@ -49,6 +49,16 @@ struct auth_xfer;
 struct module_env;
 struct auth_load_task;
 
+/**
+ * General information for auth load threads. The number of active threads.
+ */
+struct auth_load_general_info {
+       /** lock on this structure */
+       lock_basic_type lock;
+       /** The number of active auth load threads. */
+       int num_auth_load_threads;
+};
+
 /**
  * The types of notifications that the auth load thread sends around.
  */
@@ -159,4 +169,30 @@ int auth_load_add_task_xfr(struct auth_xfer* xfr, struct worker* worker);
 /** See if there is a quit signal, true if so. */
 int auth_load_thread_poll_for_quit(struct auth_load_thread* thr);
 
+/**
+ * Create auth load info structure.
+ * @return NULL on failure.
+ */
+struct auth_load_general_info* auth_load_info_create(void);
+
+/**
+ * Delete auth load info structure.
+ * @param auth_load_info: to delete.
+ */
+void auth_load_info_delete(struct auth_load_general_info* auth_load_info);
+
+/**
+ * Grab a new thread from the auth load count.
+ * @param env: with auth_load_info with the active thread count.
+ *     and config file, with configured maximum.
+ * @return false on failure, like too many active, true if successful.
+ */
+int auth_load_info_grab_thread(struct module_env* env);
+
+/**
+ * Release thread from auth load count. It is done.
+ * @param env: with auth_load_info with the active thread count.
+ */
+void auth_load_info_release_thread(struct module_env* env);
+
 #endif /* SERVICES_AUTHLOAD_H */
index 64fc391007f66ca418caaaff20ac4240bf42f56e..503347440aa71527bbd355dd5d54b8ffae61af79 100644 (file)
@@ -6391,15 +6391,20 @@ static void
 process_list_end_transfer(struct auth_xfer* xfr, struct module_env* env)
 {
        int ixfr_fail = 0;
-       if(env->cfg->auth_task_threads != 0 /* auth load enabled */ ) {
-               /* Create auth load thread task to process the data. */
-               if(auth_load_add_task_xfr(xfr, env->worker)) {
-                       /* Task is created, wait for it to be done. The worker
-                        * is signalled with the result. */
-                       /* When it is done, the xfr_process_load_end_transfer
-                        * routine is called. */
-                       lock_basic_unlock(&xfr->lock);
-                       return;
+       if(env->cfg->auth_task_threads != 0 /* auth load enabled */) {
+               if(auth_load_info_grab_thread(env)) {
+                       /* Create auth load thread task to process the data. */
+                       if(auth_load_add_task_xfr(xfr, env->worker)) {
+                               /* Task is created, wait for it to be done. The worker
+                                * is signalled with the result. */
+                               /* When it is done, the xfr_process_load_end_transfer
+                                * routine is called. */
+                               lock_basic_unlock(&xfr->lock);
+                               return;
+                       }
+                       auth_load_info_release_thread(env);
+               } else {
+                       verbose(VERB_ALGO, "Auth load threads at capacity, not creating a new thread");
                }
        } else if(xfr_process_chunk_list(xfr, env, &ixfr_fail)) {
                /* it worked! */