[PATCH v12a 1/4] Refactor how some aux processes advertise their ProcNumber
Heikki Linnakangas <heikki.linnakangas@iki.fi>
From: Heikki Linnakangas <heikki.linnakangas@iki.fi>
To:
Date: 2026-02-13T12:23:35Z
Lists: pgsql-hackers
This moves the responsibility of setting the
ProcGlobal->walrewriterProc and checkpointerProc fields to
InitAuxiliaryProcess. Also switch to the same pattern to advertise the
autovacuum launcher's ProcNumber, replacing the ad hoc av_launcherpid
field in shared memory. This can easily be extended to other aux
processes in the future, if other processes need to find them.
Switch to pg_atomic_uint32 for the fields. Seems easier to reason
about than volatile pointers. There was some precedence for that, as
were already using pg_atomic_uint32 for the procArrayGroupFirst and
clogGroupFirst fields, which also store ProcNumbers.
TODO: could also replace WalRecv->procno with this
---
src/include/storage/proc.h | 7 ++++---
src/backend/access/transam/xlog.c | 3 +--
src/backend/postmaster/autovacuum.c | 19 +++++++++--------
src/backend/postmaster/checkpointer.c | 14 ++++---------
src/backend/postmaster/walwriter.c | 6 ------
src/backend/storage/lmgr/proc.c | 30 +++++++++++++++++++++++++--
6 files changed, 47 insertions(+), 32 deletions(-)
diff --git a/src/include/storage/proc.h b/src/include/storage/proc.h
index 3f89450c216..4a1fafb9038 100644
--- a/src/include/storage/proc.h
+++ b/src/include/storage/proc.h
@@ -488,11 +488,12 @@ typedef struct PROC_HDR
pg_atomic_uint32 clogGroupFirst;
/*
- * Current slot numbers of some auxiliary processes. There can be only one
+ * Current proc numbers of some auxiliary processes. There can be only one
* of each of these running at a time.
*/
- ProcNumber walwriterProc;
- ProcNumber checkpointerProc;
+ pg_atomic_uint32 avLauncherProc;
+ pg_atomic_uint32 walwriterProc;
+ pg_atomic_uint32 checkpointerProc;
/* Current shared estimate of appropriate spins_per_delay value */
int spins_per_delay;
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index b9b678f3722..0b5ad4dc79c 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2637,8 +2637,7 @@ XLogSetAsyncXactLSN(XLogRecPtr asyncXactLSN)
if (wakeup)
{
- volatile PROC_HDR *procglobal = ProcGlobal;
- ProcNumber walwriterProc = procglobal->walwriterProc;
+ ProcNumber walwriterProc = pg_atomic_read_u32(&ProcGlobal->walwriterProc);
if (walwriterProc != INVALID_PROC_NUMBER)
SetLatch(&GetPGProcByNumber(walwriterProc)->procLatch);
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index 695e187ba11..74574e1eaf9 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -278,7 +278,6 @@ typedef struct AutoVacuumWorkItem
* struct and the array of WorkerInfo structs. This struct keeps:
*
* av_signal set by other processes to indicate various conditions
- * av_launcherpid the PID of the autovacuum launcher
* av_freeWorkers the WorkerInfo freelist
* av_runningWorkers the WorkerInfo non-free queue
* av_startingWorker pointer to WorkerInfo currently being started (cleared by
@@ -294,7 +293,6 @@ typedef struct AutoVacuumWorkItem
typedef struct
{
sig_atomic_t av_signal[AutoVacNumSignals];
- pid_t av_launcherpid;
dclist_head av_freeWorkers;
dlist_head av_runningWorkers;
WorkerInfo av_startingWorker;
@@ -565,8 +563,6 @@ AutoVacLauncherMain(const void *startup_data, size_t startup_data_len)
proc_exit(0); /* done */
}
- AutoVacuumShmem->av_launcherpid = MyProcPid;
-
/*
* Create the initial database list. The invariant we want this list to
* keep is that it's ordered by decreasing next_worker. As soon as an
@@ -800,8 +796,6 @@ AutoVacLauncherShutdown(void)
{
ereport(DEBUG1,
(errmsg_internal("autovacuum launcher shutting down")));
- AutoVacuumShmem->av_launcherpid = 0;
-
proc_exit(0); /* done */
}
@@ -1532,6 +1526,8 @@ AutoVacWorkerMain(const void *startup_data, size_t startup_data_len)
*/
if (AutoVacuumShmem->av_startingWorker != NULL)
{
+ ProcNumber launcherProc;
+
MyWorkerInfo = AutoVacuumShmem->av_startingWorker;
dbid = MyWorkerInfo->wi_dboid;
MyWorkerInfo->wi_proc = MyProc;
@@ -1550,8 +1546,14 @@ AutoVacWorkerMain(const void *startup_data, size_t startup_data_len)
on_shmem_exit(FreeWorkerInfo, 0);
/* wake up the launcher */
- if (AutoVacuumShmem->av_launcherpid != 0)
- kill(AutoVacuumShmem->av_launcherpid, SIGUSR2);
+ launcherProc = pg_atomic_read_u32(&ProcGlobal->avLauncherProc);
+ if (launcherProc != INVALID_PROC_NUMBER)
+ {
+ int pid = GetPGProcByNumber(launcherProc)->pid;
+
+ if (pid != 0)
+ kill(pid, SIGUSR2);
+ }
}
else
{
@@ -3394,7 +3396,6 @@ AutoVacuumShmemInit(void)
Assert(!found);
- AutoVacuumShmem->av_launcherpid = 0;
dclist_init(&AutoVacuumShmem->av_freeWorkers);
dlist_init(&AutoVacuumShmem->av_runningWorkers);
AutoVacuumShmem->av_startingWorker = NULL;
diff --git a/src/backend/postmaster/checkpointer.c b/src/backend/postmaster/checkpointer.c
index 3c982c6ffac..e4075265495 100644
--- a/src/backend/postmaster/checkpointer.c
+++ b/src/backend/postmaster/checkpointer.c
@@ -47,6 +47,7 @@
#include "libpq/pqsignal.h"
#include "miscadmin.h"
#include "pgstat.h"
+#include "port/atomics.h"
#include "postmaster/auxprocess.h"
#include "postmaster/bgwriter.h"
#include "postmaster/interrupt.h"
@@ -349,12 +350,6 @@ CheckpointerMain(const void *startup_data, size_t startup_data_len)
*/
UpdateSharedMemoryConfig();
- /*
- * Advertise our proc number that backends can use to wake us up while
- * we're sleeping.
- */
- ProcGlobal->checkpointerProc = MyProcNumber;
-
/*
* Loop until we've been asked to write the shutdown checkpoint or
* terminate.
@@ -1126,7 +1121,7 @@ RequestCheckpoint(int flags)
for (ntries = 0;; ntries++)
{
volatile PROC_HDR *procglobal = ProcGlobal;
- ProcNumber checkpointerProc = procglobal->checkpointerProc;
+ ProcNumber checkpointerProc = pg_atomic_read_u32(&procglobal->checkpointerProc);
if (checkpointerProc == INVALID_PROC_NUMBER)
{
@@ -1267,8 +1262,7 @@ ForwardSyncRequest(const FileTag *ftag, SyncRequestType type)
/* ... but not till after we release the lock */
if (too_full)
{
- volatile PROC_HDR *procglobal = ProcGlobal;
- ProcNumber checkpointerProc = procglobal->checkpointerProc;
+ ProcNumber checkpointerProc = pg_atomic_read_u32(&ProcGlobal->checkpointerProc);
if (checkpointerProc != INVALID_PROC_NUMBER)
SetLatch(&GetPGProcByNumber(checkpointerProc)->procLatch);
@@ -1549,7 +1543,7 @@ void
WakeupCheckpointer(void)
{
volatile PROC_HDR *procglobal = ProcGlobal;
- ProcNumber checkpointerProc = procglobal->checkpointerProc;
+ ProcNumber checkpointerProc = pg_atomic_read_u32(&procglobal->checkpointerProc);
if (checkpointerProc != INVALID_PROC_NUMBER)
SetLatch(&GetPGProcByNumber(checkpointerProc)->procLatch);
diff --git a/src/backend/postmaster/walwriter.c b/src/backend/postmaster/walwriter.c
index 9cd86ad7022..2c3b4f831aa 100644
--- a/src/backend/postmaster/walwriter.c
+++ b/src/backend/postmaster/walwriter.c
@@ -206,12 +206,6 @@ WalWriterMain(const void *startup_data, size_t startup_data_len)
hibernating = false;
SetWalWriterSleeping(false);
- /*
- * Advertise our proc number that backends can use to wake us up while
- * we're sleeping.
- */
- ProcGlobal->walwriterProc = MyProcNumber;
-
/*
* Loop forever
*/
diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c
index daf70d9ce2a..2c241cb0244 100644
--- a/src/backend/storage/lmgr/proc.c
+++ b/src/backend/storage/lmgr/proc.c
@@ -212,8 +212,9 @@ InitProcGlobal(void)
dlist_init(&ProcGlobal->bgworkerFreeProcs);
dlist_init(&ProcGlobal->walsenderFreeProcs);
ProcGlobal->startupBufferPinWaitBufId = -1;
- ProcGlobal->walwriterProc = INVALID_PROC_NUMBER;
- ProcGlobal->checkpointerProc = INVALID_PROC_NUMBER;
+ pg_atomic_init_u32(&ProcGlobal->avLauncherProc, INVALID_PROC_NUMBER);
+ pg_atomic_init_u32(&ProcGlobal->walwriterProc, INVALID_PROC_NUMBER);
+ pg_atomic_init_u32(&ProcGlobal->checkpointerProc, INVALID_PROC_NUMBER);
pg_atomic_init_u32(&ProcGlobal->procArrayGroupFirst, INVALID_PROC_NUMBER);
pg_atomic_init_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER);
@@ -712,6 +713,14 @@ InitAuxiliaryProcess(void)
*/
PGSemaphoreReset(MyProc->sem);
+ /* Some aux processes are also advertised in ProcGlobal */
+ if (MyBackendType == B_AUTOVAC_LAUNCHER)
+ pg_atomic_write_u32(&ProcGlobal->avLauncherProc, MyProcNumber);
+ if (MyBackendType == B_WAL_WRITER)
+ pg_atomic_write_u32(&ProcGlobal->walwriterProc, MyProcNumber);
+ if (MyBackendType == B_CHECKPOINTER)
+ pg_atomic_write_u32(&ProcGlobal->checkpointerProc, MyProcNumber);
+
/*
* Arrange to clean up at process exit.
*/
@@ -1056,6 +1065,23 @@ AuxiliaryProcKill(int code, Datum arg)
SwitchBackToLocalLatch();
pgstat_reset_wait_event_storage();
+ /* If this was one of aux processes advertised in ProcGlobal, clear it */
+ if (MyBackendType == B_AUTOVAC_LAUNCHER)
+ {
+ Assert(pg_atomic_read_u32(&ProcGlobal->avLauncherProc) == MyProcNumber);
+ pg_atomic_write_u32(&ProcGlobal->avLauncherProc, INVALID_PROC_NUMBER);
+ }
+ if (MyBackendType == B_WAL_WRITER)
+ {
+ Assert(pg_atomic_read_u32(&ProcGlobal->walwriterProc) == MyProcNumber);
+ pg_atomic_write_u32(&ProcGlobal->walwriterProc, INVALID_PROC_NUMBER);
+ }
+ if (MyBackendType == B_CHECKPOINTER)
+ {
+ Assert(pg_atomic_read_u32(&ProcGlobal->checkpointerProc) == MyProcNumber);
+ pg_atomic_write_u32(&ProcGlobal->checkpointerProc, INVALID_PROC_NUMBER);
+ }
+
proc = MyProc;
MyProc = NULL;
MyProcNumber = INVALID_PROC_NUMBER;
--
2.53.0.1.gb2826b52eb
--3rzmtywijtp4k7v2
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
filename="v12a-0002-Centralize-resetting-SIGCHLD-handler.patch"