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: <948b0c7df6>
Signed-off-by: Alex Chen <alexdcdc@gmail.com>
This commit is contained in:
Valentin Bartenev 2026-04-03 23:04:23 -04:00 committed by Alex Chen
parent 5eaf45f11e
commit 12817db534
5 changed files with 62 additions and 32 deletions

View file

@ -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);

View file

@ -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;
};

View file

@ -11,6 +11,7 @@
#include <ngx_channel.h>
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);

View file

@ -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)

View file

@ -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_ */