From 74cc49e6c4b8217128aff2a67afc93f986fdcc41 Mon Sep 17 00:00:00 2001 From: Yorgos Thessalonikefs Date: Fri, 23 Jan 2026 17:15:14 +0100 Subject: [PATCH] - Introduce the 'log-thread-id' configuration option to manage logging the system-wide Linux thread ID for easier debugging with system tools. --- daemon/daemon.c | 2 +- daemon/remote.c | 3 ++- dnstap/dtstream.c | 2 +- doc/example.conf.in | 4 ++++ doc/unbound.conf.rst | 9 +++++++++ util/config_file.c | 3 +++ util/config_file.h | 2 ++ util/configlexer.lex | 1 + util/configparser.y | 13 +++++++++++-- 9 files changed, 34 insertions(+), 5 deletions(-) diff --git a/daemon/daemon.c b/daemon/daemon.c index eb27fd3ab..dd9afa3d0 100644 --- a/daemon/daemon.c +++ b/daemon/daemon.c @@ -643,7 +643,7 @@ set_log_thread_id(struct worker* worker, struct config_file* cfg) log_assert(worker); #if defined(HAVE_GETTID) && !defined(THREADS_DISABLED) worker->thread_tid = gettid(); - if(1/*cfg->log_thread_id*/) + if(cfg->log_thread_id) log_thread_set(&worker->thread_tid); else #endif diff --git a/daemon/remote.c b/daemon/remote.c index 9732ace6d..1754cc84a 100644 --- a/daemon/remote.c +++ b/daemon/remote.c @@ -5968,6 +5968,7 @@ fr_atomic_copy_cfg(struct config_file* oldcfg, struct config_file* cfg, COPY_VAR_int(log_servfail); COPY_VAR_ptr(log_identity); COPY_VAR_int(log_destaddr); + COPY_VAR_int(log_thread_id); COPY_VAR_int(hide_identity); COPY_VAR_int(hide_version); COPY_VAR_int(hide_trustanchor); @@ -7023,7 +7024,7 @@ fast_reload_thread_setup(struct worker* worker, int fr_verb, int fr_nopause, lock_protect(&fr->fr_output_lock, fr->fr_output, sizeof(*fr->fr_output)); #ifdef HAVE_GETTID - fr->thread_tid_log = 1; /* worker->env->cfg->log_thread_id */ + fr->thread_tid_log = worker->env.cfg->log_thread_id; #endif return 1; } diff --git a/dnstap/dtstream.c b/dnstap/dtstream.c index 748305ce7..30db6f219 100644 --- a/dnstap/dtstream.c +++ b/dnstap/dtstream.c @@ -449,7 +449,7 @@ int dt_io_thread_apply_cfg(struct dt_io_thread* dtio, struct config_file *cfg) #endif /* HAVE_SSL */ } #ifdef HAVE_GETTID - dtio->thread_tid_log = 1 /*cfg->log_thread_id*/; + dtio->thread_tid_log = cfg->log_thread_id; #endif return 1; } diff --git a/doc/example.conf.in b/doc/example.conf.in index 296dabbd2..d84c8b3fa 100644 --- a/doc/example.conf.in +++ b/doc/example.conf.in @@ -496,6 +496,10 @@ server: # print log lines that say why queries return SERVFAIL to clients. # log-servfail: no + # log system-wide Linux thread ID, insted of Unbound's internal thread + # counter. Only on Linux and only when threads are available. + # log-thread-id: no + # the pid file. Can be an absolute path outside of chroot/work dir. # pidfile: "@UNBOUND_PIDFILE@" diff --git a/doc/unbound.conf.rst b/doc/unbound.conf.rst index 8f78fb31d..e2ea16ce3 100644 --- a/doc/unbound.conf.rst +++ b/doc/unbound.conf.rst @@ -1714,6 +1714,15 @@ These options are part of the ``server:`` section. Default: no +@@UAHL@unbound.conf@log-thread-id@@: ** + (Only on Linux and only when threads are available) + Logs the system-wide Linux thread ID instead of Unbound's internal thread + counter. + Can be useful when debugging with system tools. + + Default: no + + @@UAHL@unbound.conf@pidfile@@: ** The process id is written to the file. Default is :file:`"@UNBOUND_PIDFILE@"`. diff --git a/util/config_file.c b/util/config_file.c index 8fd0abba9..8f3e46289 100644 --- a/util/config_file.c +++ b/util/config_file.c @@ -148,6 +148,7 @@ config_create(void) cfg->log_local_actions = 0; cfg->log_servfail = 0; cfg->log_destaddr = 0; + cfg->log_thread_id = 0; #ifndef USE_WINSOCK # ifdef USE_MINI_EVENT /* select max 1024 sockets */ @@ -748,6 +749,7 @@ int config_set_option(struct config_file* cfg, const char* opt, else S_YNO("log-local-actions:", log_local_actions) else S_YNO("log-servfail:", log_servfail) else S_YNO("log-destaddr:", log_destaddr) + else S_YNO("log-thread-id:", log_thread_id) else S_YNO("val-permissive-mode:", val_permissive_mode) else S_YNO("aggressive-nsec:", aggressive_nsec) else S_YNO("ignore-cd-flag:", ignore_cd) @@ -1205,6 +1207,7 @@ config_get_option(struct config_file* cfg, const char* opt, else O_YNO(opt, "log-local-actions", log_local_actions) else O_YNO(opt, "log-servfail", log_servfail) else O_YNO(opt, "log-destaddr", log_destaddr) + else O_YNO(opt, "log-thread-id", log_thread_id) else O_STR(opt, "pidfile", pidfile) else O_YNO(opt, "hide-identity", hide_identity) else O_YNO(opt, "hide-version", hide_version) diff --git a/util/config_file.h b/util/config_file.h index ebdc1b34d..aff3fd78b 100644 --- a/util/config_file.h +++ b/util/config_file.h @@ -367,6 +367,8 @@ struct config_file { char* log_identity; /** log dest addr for log_replies */ int log_destaddr; + /** log linux thread ID */ + int log_thread_id; /** do not report identity (id.server, hostname.bind) */ int hide_identity; diff --git a/util/configlexer.lex b/util/configlexer.lex index 22f98e464..566de49ab 100644 --- a/util/configlexer.lex +++ b/util/configlexer.lex @@ -441,6 +441,7 @@ log-tag-queryreply{COLON} { YDVAR(1, VAR_LOG_TAG_QUERYREPLY) } log-local-actions{COLON} { YDVAR(1, VAR_LOG_LOCAL_ACTIONS) } log-servfail{COLON} { YDVAR(1, VAR_LOG_SERVFAIL) } log-destaddr{COLON} { YDVAR(1, VAR_LOG_DESTADDR) } +log-thread-id{COLON} { YDVAR(1, VAR_LOG_THREAD_ID) } local-zone{COLON} { YDVAR(2, VAR_LOCAL_ZONE) } local-data{COLON} { YDVAR(1, VAR_LOCAL_DATA) } local-data-ptr{COLON} { YDVAR(1, VAR_LOCAL_DATA_PTR) } diff --git a/util/configparser.y b/util/configparser.y index bf9c196fc..1bb9d84b5 100644 --- a/util/configparser.y +++ b/util/configparser.y @@ -216,7 +216,7 @@ extern struct config_parser_state* cfg_parser; %token VAR_LOG_DESTADDR VAR_CACHEDB_CHECK_WHEN_SERVE_EXPIRED %token VAR_COOKIE_SECRET_FILE VAR_ITER_SCRUB_NS VAR_ITER_SCRUB_CNAME %token VAR_MAX_GLOBAL_QUOTA VAR_HARDEN_UNVERIFIED_GLUE VAR_LOG_TIME_ISO -%token VAR_ITER_SCRUB_PROMISCUOUS +%token VAR_ITER_SCRUB_PROMISCUOUS VAR_LOG_THREAD_ID %% toplevelvars: /* empty */ | toplevelvars toplevelvar ; @@ -288,7 +288,7 @@ content_server: server_num_threads | server_verbosity | server_port | server_edns_buffer_size | server_prefetch | server_prefetch_key | server_so_sndbuf | server_harden_below_nxdomain | server_ignore_cd_flag | server_log_queries | server_log_replies | server_tcp_upstream | server_ssl_upstream | - server_log_local_actions | + server_log_local_actions | server_log_thread_id | server_ssl_service_key | server_ssl_service_pem | server_ssl_port | server_https_port | server_http_endpoint | server_http_max_streams | server_http_query_buffer_size | server_http_response_buffer_size | @@ -1347,6 +1347,15 @@ server_log_destaddr: VAR_LOG_DESTADDR STRING_ARG free($2); } ; +server_log_thread_id: VAR_LOG_THREAD_ID STRING_ARG + { + OUTYY(("P(server_log_thread_id:%s)\n", $2)); + if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) + yyerror("expected yes or no."); + else cfg_parser->cfg->log_thread_id = (strcmp($2, "yes")==0); + free($2); + } + ; server_log_local_actions: VAR_LOG_LOCAL_ACTIONS STRING_ARG { OUTYY(("P(server_log_local_actions:%s)\n", $2)); -- 2.47.3