From 0a99a16741977ef2b10ebee8198692e818f8b700 Mon Sep 17 00:00:00 2001
From: Heikki Linnakangas <heikki.linnakangas@iki.fi>
Date: Sun, 18 Jun 2023 12:45:50 +0300
Subject: [PATCH 2/9] Pass background worker entry in the parameter file

This makes it possible to move InitProcess later in SubPostmasterMain
(in next commit), as we don't need an lwlock and hence a PGPROC entry
to get the background worker entry anymore.
---
 src/backend/postmaster/bgworker.c           | 21 ------------
 src/backend/postmaster/postmaster.c         | 37 ++++++++++++++-------
 src/include/postmaster/bgworker_internals.h |  4 ---
 3 files changed, 25 insertions(+), 37 deletions(-)

diff --git a/src/backend/postmaster/bgworker.c b/src/backend/postmaster/bgworker.c
index 07ac68f50bc..b7140306e43 100644
--- a/src/backend/postmaster/bgworker.c
+++ b/src/backend/postmaster/bgworker.c
@@ -628,27 +628,6 @@ ResetBackgroundWorkerCrashTimes(void)
 	}
 }
 
-#ifdef EXEC_BACKEND
-/*
- * In EXEC_BACKEND mode, workers use this to retrieve their details from
- * shared memory.
- */
-BackgroundWorker *
-BackgroundWorkerEntry(int slotno)
-{
-	static BackgroundWorker myEntry;
-	BackgroundWorkerSlot *slot;
-
-	Assert(slotno < BackgroundWorkerData->total_slots);
-	slot = &BackgroundWorkerData->slot[slotno];
-	Assert(slot->in_use);
-
-	/* must copy this in case we don't intend to retain shmem access */
-	memcpy(&myEntry, &slot->worker, sizeof myEntry);
-	return &myEntry;
-}
-#endif
-
 /*
  * Complain about the BackgroundWorker definition using error level elevel.
  * Return true if it looks ok, false if not (unless elevel >= ERROR, in
diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index ee9e24e4e74..a7a9e061c5b 100644
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -540,6 +540,8 @@ typedef struct
 #endif
 	char		my_exec_path[MAXPGPATH];
 	char		pkglib_path[MAXPGPATH];
+
+	BackgroundWorker MyBgworkerEntry;
 } BackendParameters;
 
 static void read_backend_variables(char *id, Port *port);
@@ -4867,7 +4869,7 @@ SubPostmasterMain(int argc, char *argv[])
 		strcmp(argv[1], "--forkavlauncher") == 0 ||
 		strcmp(argv[1], "--forkavworker") == 0 ||
 		strcmp(argv[1], "--forkaux") == 0 ||
-		strncmp(argv[1], "--forkbgworker=", 15) == 0)
+		strncmp(argv[1], "--forkbgworker", 14) == 0)
 		PGSharedMemoryReAttach();
 	else
 		PGSharedMemoryNoReAttach();
@@ -4998,10 +5000,8 @@ SubPostmasterMain(int argc, char *argv[])
 
 		AutoVacWorkerMain(argc - 2, argv + 2);	/* does not return */
 	}
-	if (strncmp(argv[1], "--forkbgworker=", 15) == 0)
+	if (strncmp(argv[1], "--forkbgworker", 14) == 0)
 	{
-		int			shmem_slot;
-
 		/* do this as early as possible; in particular, before InitProcess() */
 		IsBackgroundWorker = true;
 
@@ -5014,10 +5014,6 @@ SubPostmasterMain(int argc, char *argv[])
 		/* Attach process to shared data structures */
 		CreateSharedMemoryAndSemaphores();
 
-		/* Fetch MyBgworkerEntry from shared memory */
-		shmem_slot = atoi(argv[1] + 15);
-		MyBgworkerEntry = BackgroundWorkerEntry(shmem_slot);
-
 		StartBackgroundWorker();
 	}
 	if (strcmp(argv[1], "--forklog") == 0)
@@ -5662,13 +5658,14 @@ BackgroundWorkerUnblockSignals(void)
 
 #ifdef EXEC_BACKEND
 static pid_t
-bgworker_forkexec(int shmem_slot)
+bgworker_forkexec(BackgroundWorker *worker)
 {
 	char	   *av[10];
 	int			ac = 0;
 	char		forkav[MAXPGPATH];
+	pid_t		result;
 
-	snprintf(forkav, MAXPGPATH, "--forkbgworker=%d", shmem_slot);
+	snprintf(forkav, MAXPGPATH, "--forkbgworker");
 
 	av[ac++] = "postgres";
 	av[ac++] = forkav;
@@ -5677,7 +5674,11 @@ bgworker_forkexec(int shmem_slot)
 
 	Assert(ac < lengthof(av));
 
-	return postmaster_forkexec(ac, av);
+	MyBgworkerEntry = worker;
+	result = postmaster_forkexec(ac, av);
+	MyBgworkerEntry = NULL;
+
+	return result;
 }
 #endif
 
@@ -5718,7 +5719,7 @@ do_start_bgworker(RegisteredBgWorker *rw)
 							 rw->rw_worker.bgw_name)));
 
 #ifdef EXEC_BACKEND
-	switch ((worker_pid = bgworker_forkexec(rw->rw_shmem_slot)))
+	switch ((worker_pid = bgworker_forkexec(&rw->rw_worker)))
 #else
 	switch ((worker_pid = fork_process()))
 #endif
@@ -6120,6 +6121,11 @@ save_backend_variables(BackendParameters *param, Port *port,
 
 	strlcpy(param->pkglib_path, pkglib_path, MAXPGPATH);
 
+	if (MyBgworkerEntry)
+		memcpy(&param->MyBgworkerEntry, MyBgworkerEntry, sizeof(BackgroundWorker));
+	else
+		memset(&param->MyBgworkerEntry, 0, sizeof(BackgroundWorker));
+
 	return true;
 }
 
@@ -6350,6 +6356,13 @@ restore_backend_variables(BackendParameters *param, Port *port)
 
 	strlcpy(pkglib_path, param->pkglib_path, MAXPGPATH);
 
+	if (param->MyBgworkerEntry.bgw_name[0] != '\0')
+	{
+		MyBgworkerEntry = (BackgroundWorker *)
+			MemoryContextAlloc(TopMemoryContext, sizeof(BackgroundWorker));
+		memcpy(MyBgworkerEntry, &param->MyBgworkerEntry, sizeof(BackgroundWorker));
+	}
+
 	/*
 	 * We need to restore fd.c's counts of externally-opened FDs; to avoid
 	 * confusion, be sure to do this after restoring max_safe_fds.  (Note:
diff --git a/src/include/postmaster/bgworker_internals.h b/src/include/postmaster/bgworker_internals.h
index 4ad63fd9bd7..7fa7ee2d878 100644
--- a/src/include/postmaster/bgworker_internals.h
+++ b/src/include/postmaster/bgworker_internals.h
@@ -57,8 +57,4 @@ extern void ResetBackgroundWorkerCrashTimes(void);
 /* Function to start a background worker, called from postmaster.c */
 extern void StartBackgroundWorker(void) pg_attribute_noreturn();
 
-#ifdef EXEC_BACKEND
-extern BackgroundWorker *BackgroundWorkerEntry(int slotno);
-#endif
-
 #endif							/* BGWORKER_INTERNALS_H */
-- 
2.30.2

