diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2024-12-28 12:30:42 -0500 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2024-12-28 12:30:42 -0500 |
commit | 14141bbbc103bf5db41c8f9a8206dfc9ca626e9f (patch) | |
tree | 1f9dd728e9dab97bae8620824d63b4014fa3404a /src/backend/storage/lmgr/proc.c | |
parent | a46311ed7214741ad0d38893da4285b2c2b468ad (diff) | |
download | postgresql-14141bbbc103bf5db41c8f9a8206dfc9ca626e9f.tar.gz postgresql-14141bbbc103bf5db41c8f9a8206dfc9ca626e9f.zip |
Reserve a PGPROC slot and semaphore for the slotsync worker process.
The need for this was missed in commit 93db6cbda, with the result
being that if we launch a slotsync worker it would consume one of
the PGPROCs in the max_connections pool. That could lead to inability
to launch the worker, or to subsequent failures of connection requests
that should have succeeded according to the configured settings.
Rather than create some one-off infrastructure to support this,
let's group the slotsync worker with the existing autovac launcher
in a new category of "special worker" processes. These are kind of
like auxiliary processes, but they cannot use that infrastructure
because they need to be able to run transactions.
For the moment, make these processes share the PGPROC freelist
used for autovac workers (which previously supplied the autovac
launcher too). This is partly to avoid an ABI change in v17,
and partly because it seems silly to have a freelist with
at most two members. This might be worth revisiting if we grow
enough workers in this category.
Tom Lane and Hou Zhijie. Back-patch to v17.
Discussion: https://postgr.es/m/1808397.1735156190@sss.pgh.pa.us
Diffstat (limited to 'src/backend/storage/lmgr/proc.c')
-rw-r--r-- | src/backend/storage/lmgr/proc.c | 37 |
1 files changed, 21 insertions, 16 deletions
diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index ce29da90121..f15ae87659c 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -183,11 +183,12 @@ InitProcGlobal(void) /* * Create and initialize all the PGPROC structures we'll need. There are - * five separate consumers: (1) normal backends, (2) autovacuum workers - * and the autovacuum launcher, (3) background workers, (4) auxiliary - * processes, and (5) prepared transactions. Each PGPROC structure is - * dedicated to exactly one of these purposes, and they do not move - * between groups. + * six separate consumers: (1) normal backends, (2) autovacuum workers and + * special workers, (3) background workers, (4) walsenders, (5) auxiliary + * processes, and (6) prepared transactions. (For largely-historical + * reasons, we combine autovacuum and special workers into one category + * with a single freelist.) Each PGPROC structure is dedicated to exactly + * one of these purposes, and they do not move between groups. */ procs = (PGPROC *) ShmemAlloc(TotalProcs * sizeof(PGPROC)); MemSet(procs, 0, TotalProcs * sizeof(PGPROC)); @@ -229,12 +230,13 @@ InitProcGlobal(void) } /* - * Newly created PGPROCs for normal backends, autovacuum and bgworkers - * must be queued up on the appropriate free list. Because there can - * only ever be a small, fixed number of auxiliary processes, no free - * list is used in that case; InitAuxiliaryProcess() instead uses a - * linear search. PGPROCs for prepared transactions are added to a - * free list by TwoPhaseShmemInit(). + * Newly created PGPROCs for normal backends, autovacuum workers, + * special workers, bgworkers, and walsenders must be queued up on the + * appropriate free list. Because there can only ever be a small, + * fixed number of auxiliary processes, no free list is used in that + * case; InitAuxiliaryProcess() instead uses a linear search. PGPROCs + * for prepared transactions are added to a free list by + * TwoPhaseShmemInit(). */ if (i < MaxConnections) { @@ -242,13 +244,13 @@ InitProcGlobal(void) dlist_push_tail(&ProcGlobal->freeProcs, &proc->links); proc->procgloballist = &ProcGlobal->freeProcs; } - else if (i < MaxConnections + autovacuum_max_workers + 1) + else if (i < MaxConnections + autovacuum_max_workers + NUM_SPECIAL_WORKER_PROCS) { - /* PGPROC for AV launcher/worker, add to autovacFreeProcs list */ + /* PGPROC for AV or special worker, add to autovacFreeProcs list */ dlist_push_tail(&ProcGlobal->autovacFreeProcs, &proc->links); proc->procgloballist = &ProcGlobal->autovacFreeProcs; } - else if (i < MaxConnections + autovacuum_max_workers + 1 + max_worker_processes) + else if (i < MaxConnections + autovacuum_max_workers + NUM_SPECIAL_WORKER_PROCS + max_worker_processes) { /* PGPROC for bgworker, add to bgworkerFreeProcs list */ dlist_push_tail(&ProcGlobal->bgworkerFreeProcs, &proc->links); @@ -307,8 +309,11 @@ InitProcess(void) if (MyProc != NULL) elog(ERROR, "you already exist"); - /* Decide which list should supply our PGPROC. */ - if (AmAutoVacuumLauncherProcess() || AmAutoVacuumWorkerProcess()) + /* + * Decide which list should supply our PGPROC. This logic must match the + * way the freelists were constructed in InitProcGlobal(). + */ + if (AmAutoVacuumWorkerProcess() || AmSpecialWorkerProcess()) procgloballist = &ProcGlobal->autovacFreeProcs; else if (AmBackgroundWorkerProcess()) procgloballist = &ProcGlobal->bgworkerFreeProcs; |