From 590712b4fea381a82cfaa9aa17bbe0f07ca0c16a Mon Sep 17 00:00:00 2001 From: Baji Shaik Date: Fri, 5 Jun 2026 12:40:18 -0500 Subject: [PATCH] Fix memory leak in pgstat_progress_parallel_incr_param() When called from a parallel worker, pgstat_progress_parallel_incr_param() calls initStringInfo() on a static StringInfoData and then immediately calls pq_beginmessage(), which calls initStringInfo() again. The second call overwrites buf->data with a freshly palloc'd buffer, orphaning the first one. pq_endmessage() then frees only the second buffer, so each call leaks ~1 kB into the per-worker memory context. The leak is negligible by default, but with track_cost_delay_timing enabled the parallel cost-delay reporting path fires once per second per worker, so a long-running parallel vacuum leaks megabytes per worker. Fix by initializing the static buffer once per process and using pq_beginmessage_reuse()/pq_endmessage_reuse(), so the buffer is allocated once and reused. This is an oversight of f1889729dd3 ("Add new parallel message type to progress reporting"); track_cost_delay_timing just makes it more visible. Author: Baji Shaik --- src/backend/utils/activity/backend_progress.c | 20 ++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/src/backend/utils/activity/backend_progress.c b/src/backend/utils/activity/backend_progress.c index b0359771de5..0483741a80e 100644 --- a/src/backend/utils/activity/backend_progress.c +++ b/src/backend/utils/activity/backend_progress.c @@ -99,13 +99,23 @@ pgstat_progress_parallel_incr_param(int index, int64 incr) if (IsParallelWorker()) { static StringInfoData progress_message; - - initStringInfo(&progress_message); - - pq_beginmessage(&progress_message, PqMsg_Progress); + static bool progress_message_initialized = false; + + /* + * Initialize the message buffer once per process; pq_beginmessage_reuse() + * and pq_endmessage_reuse() reset and reuse it on each call to avoid + * palloc overhead. + */ + if (!progress_message_initialized) + { + initStringInfo(&progress_message); + progress_message_initialized = true; + } + + pq_beginmessage_reuse(&progress_message, PqMsg_Progress); pq_sendint32(&progress_message, index); pq_sendint64(&progress_message, incr); - pq_endmessage(&progress_message); + pq_endmessage_reuse(&progress_message); } else pgstat_progress_incr_param(index, incr); -- 2.50.1 (Apple Git-155)