Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 14141bb

Browse files
committed
Reserve a PGPROC slot and semaphore for the slotsync worker process.
The need for this was missed in commit 93db6cb, 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
1 parent a46311e commit 14141bb

File tree

4 files changed

+43
-23
lines changed

4 files changed

+43
-23
lines changed

src/backend/storage/lmgr/proc.c

+21-16
Original file line numberDiff line numberDiff line change
@@ -183,11 +183,12 @@ InitProcGlobal(void)
183183

184184
/*
185185
* Create and initialize all the PGPROC structures we'll need. There are
186-
* five separate consumers: (1) normal backends, (2) autovacuum workers
187-
* and the autovacuum launcher, (3) background workers, (4) auxiliary
188-
* processes, and (5) prepared transactions. Each PGPROC structure is
189-
* dedicated to exactly one of these purposes, and they do not move
190-
* between groups.
186+
* six separate consumers: (1) normal backends, (2) autovacuum workers and
187+
* special workers, (3) background workers, (4) walsenders, (5) auxiliary
188+
* processes, and (6) prepared transactions. (For largely-historical
189+
* reasons, we combine autovacuum and special workers into one category
190+
* with a single freelist.) Each PGPROC structure is dedicated to exactly
191+
* one of these purposes, and they do not move between groups.
191192
*/
192193
procs = (PGPROC *) ShmemAlloc(TotalProcs * sizeof(PGPROC));
193194
MemSet(procs, 0, TotalProcs * sizeof(PGPROC));
@@ -229,26 +230,27 @@ InitProcGlobal(void)
229230
}
230231

231232
/*
232-
* Newly created PGPROCs for normal backends, autovacuum and bgworkers
233-
* must be queued up on the appropriate free list. Because there can
234-
* only ever be a small, fixed number of auxiliary processes, no free
235-
* list is used in that case; InitAuxiliaryProcess() instead uses a
236-
* linear search. PGPROCs for prepared transactions are added to a
237-
* free list by TwoPhaseShmemInit().
233+
* Newly created PGPROCs for normal backends, autovacuum workers,
234+
* special workers, bgworkers, and walsenders must be queued up on the
235+
* appropriate free list. Because there can only ever be a small,
236+
* fixed number of auxiliary processes, no free list is used in that
237+
* case; InitAuxiliaryProcess() instead uses a linear search. PGPROCs
238+
* for prepared transactions are added to a free list by
239+
* TwoPhaseShmemInit().
238240
*/
239241
if (i < MaxConnections)
240242
{
241243
/* PGPROC for normal backend, add to freeProcs list */
242244
dlist_push_tail(&ProcGlobal->freeProcs, &proc->links);
243245
proc->procgloballist = &ProcGlobal->freeProcs;
244246
}
245-
else if (i < MaxConnections + autovacuum_max_workers + 1)
247+
else if (i < MaxConnections + autovacuum_max_workers + NUM_SPECIAL_WORKER_PROCS)
246248
{
247-
/* PGPROC for AV launcher/worker, add to autovacFreeProcs list */
249+
/* PGPROC for AV or special worker, add to autovacFreeProcs list */
248250
dlist_push_tail(&ProcGlobal->autovacFreeProcs, &proc->links);
249251
proc->procgloballist = &ProcGlobal->autovacFreeProcs;
250252
}
251-
else if (i < MaxConnections + autovacuum_max_workers + 1 + max_worker_processes)
253+
else if (i < MaxConnections + autovacuum_max_workers + NUM_SPECIAL_WORKER_PROCS + max_worker_processes)
252254
{
253255
/* PGPROC for bgworker, add to bgworkerFreeProcs list */
254256
dlist_push_tail(&ProcGlobal->bgworkerFreeProcs, &proc->links);
@@ -307,8 +309,11 @@ InitProcess(void)
307309
if (MyProc != NULL)
308310
elog(ERROR, "you already exist");
309311

310-
/* Decide which list should supply our PGPROC. */
311-
if (AmAutoVacuumLauncherProcess() || AmAutoVacuumWorkerProcess())
312+
/*
313+
* Decide which list should supply our PGPROC. This logic must match the
314+
* way the freelists were constructed in InitProcGlobal().
315+
*/
316+
if (AmAutoVacuumWorkerProcess() || AmSpecialWorkerProcess())
312317
procgloballist = &ProcGlobal->autovacFreeProcs;
313318
else if (AmBackgroundWorkerProcess())
314319
procgloballist = &ProcGlobal->bgworkerFreeProcs;

src/backend/utils/init/postinit.c

+3-3
Original file line numberDiff line numberDiff line change
@@ -576,9 +576,9 @@ InitializeMaxBackends(void)
576576
{
577577
Assert(MaxBackends == 0);
578578

579-
/* the extra unit accounts for the autovacuum launcher */
580-
MaxBackends = MaxConnections + autovacuum_max_workers + 1 +
581-
max_worker_processes + max_wal_senders;
579+
/* Note that this does not include "auxiliary" processes */
580+
MaxBackends = MaxConnections + autovacuum_max_workers +
581+
max_worker_processes + max_wal_senders + NUM_SPECIAL_WORKER_PROCS;
582582

583583
/* internal error because the values were all checked previously */
584584
if (MaxBackends > MAX_BACKENDS)

src/include/miscadmin.h

+7-2
Original file line numberDiff line numberDiff line change
@@ -346,8 +346,9 @@ typedef enum BackendType
346346

347347
/*
348348
* Auxiliary processes. These have PGPROC entries, but they are not
349-
* attached to any particular database. There can be only one of each of
350-
* these running at a time.
349+
* attached to any particular database, and cannot run transactions or
350+
* even take heavyweight locks. There can be only one of each of these
351+
* running at a time.
351352
*
352353
* If you modify these, make sure to update NUM_AUXILIARY_PROCS and the
353354
* glossary in the docs.
@@ -384,6 +385,10 @@ extern PGDLLIMPORT BackendType MyBackendType;
384385
#define AmWalSummarizerProcess() (MyBackendType == B_WAL_SUMMARIZER)
385386
#define AmWalWriterProcess() (MyBackendType == B_WAL_WRITER)
386387

388+
#define AmSpecialWorkerProcess() \
389+
(AmAutoVacuumLauncherProcess() || \
390+
AmLogicalSlotSyncWorkerProcess())
391+
387392
extern const char *GetBackendTypeDesc(BackendType backendType);
388393

389394
extern void SetDatabasePath(const char *path);

src/include/storage/proc.h

+12-2
Original file line numberDiff line numberDiff line change
@@ -404,7 +404,7 @@ typedef struct PROC_HDR
404404
uint32 allProcCount;
405405
/* Head of list of free PGPROC structures */
406406
dlist_head freeProcs;
407-
/* Head of list of autovacuum's free PGPROC structures */
407+
/* Head of list of autovacuum & special worker free PGPROC structures */
408408
dlist_head autovacFreeProcs;
409409
/* Head of list of bgworker free PGPROC structures */
410410
dlist_head bgworkerFreeProcs;
@@ -434,9 +434,19 @@ extern PGDLLIMPORT PGPROC *PreparedXactProcs;
434434
#define GetPGProcByNumber(n) (&ProcGlobal->allProcs[(n)])
435435
#define GetNumberFromPGProc(proc) ((proc) - &ProcGlobal->allProcs[0])
436436

437+
/*
438+
* We set aside some extra PGPROC structures for "special worker" processes,
439+
* which are full-fledged backends (they can run transactions)
440+
* but are unique animals that there's never more than one of.
441+
* Currently there are two such processes: the autovacuum launcher
442+
* and the slotsync worker.
443+
*/
444+
#define NUM_SPECIAL_WORKER_PROCS 2
445+
437446
/*
438447
* We set aside some extra PGPROC structures for auxiliary processes,
439-
* ie things that aren't full-fledged backends but need shmem access.
448+
* ie things that aren't full-fledged backends (they cannot run transactions
449+
* or take heavyweight locks) but need shmem access.
440450
*
441451
* Background writer, checkpointer, WAL writer, WAL summarizer, and archiver
442452
* run during normal operation. Startup process and WAL receiver also consume

0 commit comments

Comments
 (0)