From 42c0d060f5713111d4f71bd370b54d440608d5fd Mon Sep 17 00:00:00 2001
From: Heikki Linnakangas <heikki.linnakangas@iki.fi>
Date: Tue, 23 Jun 2026 20:58:22 +0300
Subject: [PATCH v13 3/9] Refactor datachecksums launcher/worker comms to use
 procnumber

I'm trying to eliminate using PIDs in preparation of the next patches
---
 src/backend/postmaster/datachecksum_state.c | 48 ++++++++++++++-------
 1 file changed, 33 insertions(+), 15 deletions(-)

diff --git a/src/backend/postmaster/datachecksum_state.c b/src/backend/postmaster/datachecksum_state.c
index 68557c16cb9..47b87f51ad9 100644
--- a/src/backend/postmaster/datachecksum_state.c
+++ b/src/backend/postmaster/datachecksum_state.c
@@ -209,6 +209,7 @@
 #include "storage/latch.h"
 #include "storage/lmgr.h"
 #include "storage/lwlock.h"
+#include "storage/proc.h"
 #include "storage/procarray.h"
 #include "storage/smgr.h"
 #include "storage/subsystems.h"
@@ -326,7 +327,9 @@ typedef struct DataChecksumsStateStruct
 	 */
 	uint64		worker_invocation;	/* unique invocation number */
 	Oid			database_oid;	/* database it's processing */
-	pid_t		worker_pid;		/* worker process's PID */
+
+	/* Worker process's proc number, set by the worker when it starts up */
+	ProcNumber	worker_procno;
 
 	/*
 	 * These fields indicate the target state that the worker is currently
@@ -840,7 +843,7 @@ ProcessDatabase(DataChecksumsWorkerDatabase *db)
 	 * if it completes successfully.
 	 */
 	DataChecksumState->worker_result = DATACHECKSUMSWORKER_FAILED;
-	DataChecksumState->worker_pid = InvalidPid;
+	DataChecksumState->worker_procno = INVALID_PROC_NUMBER;
 
 	invocation = ++DataChecksumState->worker_invocation_counter;
 	DataChecksumState->worker_invocation = invocation;
@@ -883,6 +886,7 @@ ProcessDatabase(DataChecksumsWorkerDatabase *db)
 		 */
 		LWLockAcquire(DataChecksumsWorkerLock, LW_SHARED);
 		Assert(DataChecksumState->worker_invocation == invocation);
+		Assert(DataChecksumState->worker_procno == INVALID_PROC_NUMBER);
 		if (DataChecksumState->worker_result == DATACHECKSUMSWORKER_SUCCESSFUL)
 		{
 			LWLockRelease(DataChecksumsWorkerLock);
@@ -924,12 +928,6 @@ ProcessDatabase(DataChecksumsWorkerDatabase *db)
 			errmsg("initiating data checksum processing in database \"%s\"",
 				   db->dbname));
 
-	/* Save the pid of the worker so we can signal it later */
-	LWLockAcquire(DataChecksumsWorkerLock, LW_EXCLUSIVE);
-	Assert(DataChecksumState->worker_invocation == invocation);
-	DataChecksumState->worker_pid = pid;
-	LWLockRelease(DataChecksumsWorkerLock);
-
 	snprintf(activity, sizeof(activity) - 1,
 			 "Waiting for worker in database %s (pid %ld)", db->dbname, (long) pid);
 	pgstat_report_activity(STATE_RUNNING, activity);
@@ -942,10 +940,10 @@ ProcessDatabase(DataChecksumsWorkerDatabase *db)
 					   db->dbname),
 				errhint("Restart the database and restart data checksum processing by calling pg_enable_data_checksums()."));
 
-	LWLockAcquire(DataChecksumsWorkerLock, LW_EXCLUSIVE);
+	LWLockAcquire(DataChecksumsWorkerLock, LW_SHARED);
 	Assert(DataChecksumState->worker_invocation == invocation);
+	Assert(DataChecksumState->worker_procno == INVALID_PROC_NUMBER);
 	result = DataChecksumState->worker_result;
-	DataChecksumState->worker_pid = InvalidPid;
 	LWLockRelease(DataChecksumsWorkerLock);
 
 	if (result == DATACHECKSUMSWORKER_ABORTED)
@@ -974,12 +972,11 @@ launcher_exit(int code, Datum arg)
 	if (launcher_running)
 	{
 		LWLockAcquire(DataChecksumsWorkerLock, LW_EXCLUSIVE);
-		if (DataChecksumState->worker_pid != InvalidPid)
+		if (DataChecksumState->worker_procno != INVALID_PROC_NUMBER)
 		{
 			ereport(LOG,
 					errmsg("data checksums launcher exiting while worker is still running, signalling worker"));
-			kill(DataChecksumState->worker_pid, SIGTERM);
-			DataChecksumState->worker_pid = InvalidPid;
+			kill(GetPGProcByNumber(DataChecksumState->worker_procno)->pid, SIGTERM);
 		}
 		LWLockRelease(DataChecksumsWorkerLock);
 	}
@@ -1092,7 +1089,6 @@ WaitForAllTransactionsToFinish(void)
 void
 DataChecksumsWorkerLauncherMain(Datum arg)
 {
-
 	ereport(DEBUG1,
 			errmsg("background worker \"datachecksums launcher\" started"));
 
@@ -1529,6 +1525,21 @@ BuildRelationList(bool temp_relations, bool include_shared)
 	return RelationList;
 }
 
+/*
+ * worker_exit
+ *
+ * Internal routine for cleaning up state when a worker process exits due to
+ * an error.
+ */
+static void
+worker_exit(int code, Datum arg)
+{
+	LWLockAcquire(DataChecksumsWorkerLock, LW_EXCLUSIVE);
+	if (DataChecksumState->worker_invocation == worker_invocation)
+		DataChecksumState->worker_procno = INVALID_PROC_NUMBER;
+	LWLockRelease(DataChecksumsWorkerLock);
+}
+
 /*
  * DataChecksumsWorkerMain
  *
@@ -1566,15 +1577,22 @@ DataChecksumsWorkerMain(Datum arg)
 	MyBackendType = B_DATACHECKSUMSWORKER_WORKER;
 	init_ps_display(NULL);
 
-	LWLockAcquire(DataChecksumsWorkerLock, LW_SHARED);
+	LWLockAcquire(DataChecksumsWorkerLock, LW_EXCLUSIVE);
 	if (DataChecksumState->worker_invocation != worker_invocation)
 	{
 		LWLockRelease(DataChecksumsWorkerLock);
 		return;
 	}
+	if (DataChecksumState->worker_procno != INVALID_PROC_NUMBER)
+		elog(ERROR, "data checksums background worker is already running");
+	DataChecksumState->worker_procno = MyProcNumber;
+
 	dboid = DataChecksumState->database_oid;
 	LWLockRelease(DataChecksumsWorkerLock);
 
+	/* Arrange to clear worker_procno on exit */
+	on_shmem_exit(worker_exit, 0);
+
 	BackgroundWorkerInitializeConnectionByOid(dboid, InvalidOid,
 											  BGWORKER_BYPASS_ALLOWCONN);
 
-- 
2.47.3

