From 12817db534a0590b7d8eaa6df4a4579b1aed0058 Mon Sep 17 00:00:00 2001 From: Valentin Bartenev Date: Fri, 3 Apr 2026 23:04:23 -0400 Subject: [PATCH] Core: add configuration generations to cycles Store a configuration generation number on each cycle and include it in Unix process titles. The first runtime cycle starts at generation 1. Successful reloads increment the generation for new master, worker, and helper processes. Refactor Unix setproctitle handling to support formatted titles while preserving the existing wrapper macro. Closes: https://github.com/nginx/nginx/issues/1238 Origin: Signed-off-by: Alex Chen --- src/core/ngx_cycle.c | 2 ++ src/core/ngx_cycle.h | 2 ++ src/os/unix/ngx_process_cycle.c | 62 +++++++++++++++++++-------------- src/os/unix/ngx_setproctitle.c | 14 ++++++-- src/os/unix/ngx_setproctitle.h | 14 +++++--- 5 files changed, 62 insertions(+), 32 deletions(-) diff --git a/src/core/ngx_cycle.c b/src/core/ngx_cycle.c index e5fd40285..4284b15ac 100644 --- a/src/core/ngx_cycle.c +++ b/src/core/ngx_cycle.c @@ -221,6 +221,8 @@ ngx_init_cycle(ngx_cycle_t *old_cycle) ngx_strlow(cycle->hostname.data, (u_char *) hostname, cycle->hostname.len); + cycle->generation = old_cycle->generation + 1; + if (ngx_cycle_modules(cycle) != NGX_OK) { ngx_destroy_pool(pool); diff --git a/src/core/ngx_cycle.h b/src/core/ngx_cycle.h index 0c47f25fe..32c322b4d 100644 --- a/src/core/ngx_cycle.h +++ b/src/core/ngx_cycle.h @@ -83,6 +83,8 @@ struct ngx_cycle_s { ngx_str_t error_log; ngx_str_t lock_file; ngx_str_t hostname; + + uint64_t generation; }; diff --git a/src/os/unix/ngx_process_cycle.c b/src/os/unix/ngx_process_cycle.c index 5bc5ce979..a002369d5 100644 --- a/src/os/unix/ngx_process_cycle.c +++ b/src/os/unix/ngx_process_cycle.c @@ -11,6 +11,7 @@ #include +static void ngx_update_process_title(ngx_cycle_t *cycle, ngx_uint_t single); static void ngx_start_worker_processes(ngx_cycle_t *cycle, ngx_int_t n, ngx_int_t type); static void ngx_start_cache_manager_processes(ngx_cycle_t *cycle, @@ -73,10 +74,6 @@ static ngx_open_file_t ngx_exit_log_file; void ngx_master_process_cycle(ngx_cycle_t *cycle) { - char *title; - u_char *p; - size_t size; - ngx_int_t i; ngx_uint_t sigio; sigset_t set; struct itimerval itv; @@ -104,25 +101,7 @@ ngx_master_process_cycle(ngx_cycle_t *cycle) sigemptyset(&set); - size = sizeof(master_process); - - for (i = 0; i < ngx_argc; i++) { - size += ngx_strlen(ngx_argv[i]) + 1; - } - - title = ngx_pnalloc(cycle->pool, size); - if (title == NULL) { - /* fatal */ - exit(2); - } - - p = ngx_cpymem(title, master_process, sizeof(master_process) - 1); - for (i = 0; i < ngx_argc; i++) { - *p++ = ' '; - p = ngx_cpystrn(p, (u_char *) ngx_argv[i], size); - } - - ngx_setproctitle(title); + ngx_update_process_title(cycle, 0); ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module); @@ -229,6 +208,7 @@ ngx_master_process_cycle(ngx_cycle_t *cycle) } ngx_cycle = cycle; + ngx_update_process_title(cycle, 0); ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module); ngx_start_worker_processes(cycle, ccf->worker_processes, @@ -280,6 +260,8 @@ ngx_single_process_cycle(ngx_cycle_t *cycle) { ngx_uint_t i; + ngx_update_process_title(cycle, 1); + if (ngx_set_environment(cycle, NULL) == NULL) { /* fatal */ exit(2); @@ -321,6 +303,7 @@ ngx_single_process_cycle(ngx_cycle_t *cycle) } ngx_cycle = cycle; + ngx_update_process_title(cycle, 1); } if (ngx_reopen) { @@ -332,6 +315,32 @@ ngx_single_process_cycle(ngx_cycle_t *cycle) } +static void +ngx_update_process_title(ngx_cycle_t *cycle, ngx_uint_t single) +{ + u_char *p, *end, args[2048]; + ngx_int_t i; + + end = args + sizeof(args) - 1; + + p = ngx_slprintf(args, end, "%s", ngx_argv[0]); + + for (i = 1; i < ngx_argc; i++) { + p = ngx_slprintf(p, end, " %s", ngx_argv[i]); + } + + if (p < end) { + *p++ = ']'; + } + + *p = '\0'; + + ngx_setproctitle_fmt("%s #%llu [%s", + single ? "single process" : (char *) master_process, + (unsigned long long) cycle->generation, args); +} + + static void ngx_start_worker_processes(ngx_cycle_t *cycle, ngx_int_t n, ngx_int_t type) { @@ -705,7 +714,7 @@ ngx_worker_process_cycle(ngx_cycle_t *cycle, void *data) ngx_worker_process_init(cycle, worker); - ngx_setproctitle("worker process"); + ngx_setproctitle_gen("worker process", cycle->generation); for ( ;; ) { @@ -729,7 +738,8 @@ ngx_worker_process_cycle(ngx_cycle_t *cycle, void *data) ngx_quit = 0; ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "gracefully shutting down"); - ngx_setproctitle("worker process is shutting down"); + ngx_setproctitle_gen("worker process is shutting down", + cycle->generation); if (!ngx_exiting) { ngx_exiting = 1; @@ -1114,7 +1124,7 @@ ngx_cache_manager_process_cycle(ngx_cycle_t *cycle, void *data) ngx_use_accept_mutex = 0; - ngx_setproctitle(ctx->name); + ngx_setproctitle_gen(ctx->name, cycle->generation); ngx_add_timer(&ev, ctx->delay); diff --git a/src/os/unix/ngx_setproctitle.c b/src/os/unix/ngx_setproctitle.c index 91afa5191..eb2159dc6 100644 --- a/src/os/unix/ngx_setproctitle.c +++ b/src/os/unix/ngx_setproctitle.c @@ -76,9 +76,11 @@ ngx_init_setproctitle(ngx_log_t *log) void -ngx_setproctitle(char *title) +ngx_setproctitle_fmt(const char *fmt, ...) { + int n; u_char *p; + va_list args; #if (NGX_SOLARIS) @@ -92,7 +94,15 @@ ngx_setproctitle(char *title) p = ngx_cpystrn((u_char *) ngx_os_argv[0], (u_char *) "nginx: ", ngx_os_argv_last - ngx_os_argv[0]); - p = ngx_cpystrn(p, (u_char *) title, ngx_os_argv_last - (char *) p); + va_start(args, fmt); + n = vsnprintf((char *) p, ngx_os_argv_last - (char *) p, fmt, args); + va_end(args); + + if (n < 0) { + n = 0; + } + + p += ngx_min((size_t) n, (size_t) (ngx_os_argv_last - (char *) p)); #if (NGX_SOLARIS) diff --git a/src/os/unix/ngx_setproctitle.h b/src/os/unix/ngx_setproctitle.h index c3636628b..37cdcac33 100644 --- a/src/os/unix/ngx_setproctitle.h +++ b/src/os/unix/ngx_setproctitle.h @@ -14,7 +14,7 @@ /* FreeBSD, NetBSD, OpenBSD */ #define ngx_init_setproctitle(log) NGX_OK -#define ngx_setproctitle(title) setproctitle("%s", title) +#define ngx_setproctitle_fmt setproctitle #else /* !NGX_HAVE_SETPROCTITLE */ @@ -27,7 +27,7 @@ #define NGX_SETPROCTITLE_PAD ' ' ngx_int_t ngx_init_setproctitle(ngx_log_t *log); -void ngx_setproctitle(char *title); +void ngx_setproctitle_fmt(const char *fmt, ...); #elif (NGX_LINUX) || (NGX_DARWIN) @@ -35,12 +35,12 @@ void ngx_setproctitle(char *title); #define NGX_SETPROCTITLE_PAD '\0' ngx_int_t ngx_init_setproctitle(ngx_log_t *log); -void ngx_setproctitle(char *title); +void ngx_setproctitle_fmt(const char *fmt, ...); #else #define ngx_init_setproctitle(log) NGX_OK -#define ngx_setproctitle(title) +static ngx_inline void ngx_setproctitle_fmt(const char *fmt, ...) { /* void */ } #endif /* OSes */ @@ -49,4 +49,10 @@ void ngx_setproctitle(char *title); #endif /* NGX_HAVE_SETPROCTITLE */ +#define ngx_setproctitle(title) ngx_setproctitle_fmt("%s", title) + +#define ngx_setproctitle_gen(title, gen) \ + ngx_setproctitle_fmt("%s #%llu", title, (unsigned long long) gen) + + #endif /* _NGX_SETPROCTITLE_H_INCLUDED_ */