BUG/MINOR: mworker/cli: fix show proc pagination using reload counter

After commit 594408cd61 ("BUG/MINOR: mworker/cli: 'show proc' is limited
by buffer size"), related to ticket #3204, the "show proc" logic
has been fixed to be able to print more than 202 processes. However, this
fix can lead to the omission of entries in case they have the same
timestamp.

To fix this, we use the unique reload counter instead of the timestamp.
On partial flush, set ctx->next_reload = child->reloads.
On resume skip entries with child->reloads >= ctx->next_reload.
Finally, we clear ctx->next_reload at the end of a complete dump so
subsequent show proc starts from the top.

Could be backported in all stable branches.
This commit is contained in:
Alexander Stephan 2025-12-30 10:56:45 +00:00 committed by William Lallemand
parent a5f274de92
commit 4c10d9c70c

View file

@ -807,7 +807,7 @@ void mworker_cleanup_proc()
struct cli_showproc_ctx {
int debug;
int next_uptime; /* uptime must be greater than this value */
int next_reload; /* reload number to resume from, 0 = from the beginning */
};
/* Displays workers and processes */
@ -825,7 +825,7 @@ static int cli_io_handler_show_proc(struct appctx *appctx)
chunk_reset(&trash);
if (ctx->next_uptime == 0) {
if (ctx->next_reload == 0) {
memprintf(&reloadtxt, "%d [failed: %d]", proc_self->reloads, proc_self->failedreloads);
chunk_printf(&trash, "#%-14s %-15s %-15s %-15s %-15s", "<PID>", "<type>", "<reloads>", "<uptime>", "<version>");
if (ctx->debug)
@ -843,12 +843,12 @@ static int cli_io_handler_show_proc(struct appctx *appctx)
ha_free(&uptime);
/* displays current processes */
if (ctx->next_uptime == 0)
if (ctx->next_reload == 0)
chunk_appendf(&trash, "# workers\n");
list_for_each_entry(child, &proc_list, list) {
/* don't display current worker if we only need the next ones */
if (ctx->next_uptime != 0)
if (ctx->next_reload != 0)
continue;
up = date.tv_sec - child->timestamp;
@ -874,15 +874,16 @@ static int cli_io_handler_show_proc(struct appctx *appctx)
return 0;
/* displays old processes */
if (old || ctx->next_uptime) { /* there's more */
if (ctx->next_uptime == 0)
if (old || ctx->next_reload) { /* there's more */
if (ctx->next_reload == 0)
chunk_appendf(&trash, "# old workers\n");
list_for_each_entry(child, &proc_list, list) {
up = date.tv_sec - child->timestamp;
if (up <= 0) /* must never be negative because of clock drift */
up = 0;
if (child->timestamp < ctx->next_uptime)
/* If we're resuming, skip entries that were already printed (reload >= ctx->next_reload) */
if (ctx->next_reload && child->reloads >= ctx->next_reload)
continue;
if (!(child->options & PROC_O_TYPE_WORKER))
@ -895,17 +896,21 @@ static int cli_io_handler_show_proc(struct appctx *appctx)
chunk_appendf(&trash, "\t\t %-15d %-15d", child->ipc_fd[0], child->ipc_fd[1]);
chunk_appendf(&trash, "\n");
ha_free(&uptime);
/* Try to flush so we can resume after this reload on next page if the buffer is full. */
if (applet_putchk(appctx, &trash) == -1) {
/* resume at this reload (exclude it on next pass) */
ctx->next_reload = child->reloads; /* resume after entries >= this reload */
return 0;
}
chunk_reset(&trash);
}
/* start from there if there's not enough place */
ctx->next_uptime = child->timestamp;
if (applet_putchk(appctx, &trash) == -1)
return 0;
}
}
/* dump complete */
/* dump complete: reset resume cursor so next 'show proc' starts from the top */
ctx->next_reload = 0;
return 1;
}