From 9fb388bc6eed50ed56d39f88e5a73764db48c812 Mon Sep 17 00:00:00 2001 From: Bharath Rupireddy Date: Sat, 26 Sep 2026 21:39:40 +0000 Subject: [PATCH v1] Fix crash in parallel autovacuum when no DSM segment can be created. When the maximum number of DSM segments has been reached, setting up a parallel context does not fail. It falls back to the leader's private memory and reports zero workers, and callers are expected to cope with that. Parallel query and manual VACUUM do, but the autovacuum part of parallel vacuum registered a segment detach callback without checking for the fallback. That crashes the autovacuum worker and takes the database through crash recovery. It also left the shared cost parameters pointing into the leader's private memory with nothing left to reset that pointer, so an error while vacuuming the table would leave a stale one behind for the next table. Hitting this is a bit difficult. The dead item store created right after the fallback normally fails with "too many dynamic shared memory segments" once the DSM segment limit is reached, so another backend has to free a segment in the small window between the two. Fix this by setting up the shared cost parameters and the detach callback only when the parallel context has workers, as there are no workers to propagate the parameters to otherwise. Oversight in commit 1ff3180ca01. Reported-by: Claude Code Author: Bharath Rupireddy Discussion: https://postgr.es/m/<> Backpatch-through: 19 --- src/backend/commands/vacuumparallel.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/backend/commands/vacuumparallel.c b/src/backend/commands/vacuumparallel.c index 4532da60c84..d4572861000 100644 --- a/src/backend/commands/vacuumparallel.c +++ b/src/backend/commands/vacuumparallel.c @@ -458,9 +458,13 @@ parallel_vacuum_init(Relation rel, Relation *indrels, int nindexes, /* * Initialize shared cost-based vacuum delay parameters if it's for - * autovacuum. + * autovacuum and the parallel context has workers. Note that the parallel + * context falls back to the leader's private memory with no workers and + * no segment when the maximum number of DSM segments has been reached. + * There are then no workers to propagate the parameters to, and no + * segment to register the detach callback on. */ - if (shared->is_autovacuum) + if (shared->is_autovacuum && pcxt->nworkers > 0) { parallel_vacuum_set_cost_parameters(&shared->cost_params); pg_atomic_init_u32(&shared->cost_params.generation, 1); -- 2.47.3