Here is also a version of Thomas's "Use Latch for bgworker state change notification patch", rebased over the "Replace latches with Interrupts" patch.

I used INTERRUPT_GENERAL_WAKEUP for the notification, as a straightforward replacement of setting the latch, but I wonder if we should have a dedicated interrupt flag for this instead.

--
Heikki Linnakangas
Neon (https://neon.tech)
From 2e81b3d3e51a66add7d7d6f70f70618194b2f01d Mon Sep 17 00:00:00 2001
From: Heikki Linnakangas <heikki.linnakan...@iki.fi>
Date: Fri, 15 Nov 2024 16:23:30 +0200
Subject: [PATCH v4 3/3] Use proc interrupt for bgworker state change
 notification.

As part of a project to remove the reliance on PIDs to identify
backends, backends that register dynamic background workers will now
receive INTERRUPT_GENERAL_WAKEUP sent directly by the postmaster when
the worker state changes.  Previously, the postmaster would send a
SIGUSR1 signal, which relied on the ProcSignal system's handler
setting the interrupt flag, with the same end effect.  Now that
intermediate step is skipped.

The field bgw_notify_pid still exists for backwards compatibility, but
has no effect and may be removed in a later release.
RegisterBackgroundWorker() now automatically assumes that the caller
would like state change notifications delivered to its proc number,
unless BGW_NO_NOTIFY is set in bgw_flags.

Removing other cases of PIDs from the bgwork API is left for later work;
this patch is concerned only with removing a dependency on ProcSignal
infrastructure that is due to be removed by a later commit.

This represents the first use of SendInterrupt() in the postmaster.
It might seem more natural to use condition variables in the
wait-for-state-change functions, so that anyone with a handle can
wait, but condition variables as currently implemented would be a lot
less robust that simple interrupts.

Author: Thomas Munro <thomas.mu...@gmail.com>
Reviewed-by: Heikki Linnakangas <hlinn...@iki.fi>
Discussion: https://postgr.es/m/CA%2BhUKG%2B3MkS21yK4jL4cgZywdnnGKiBg0jatoV6kzaniBmcqbQ%40mail.gmail.com
---
 contrib/pg_prewarm/autoprewarm.c            |   6 -
 doc/src/sgml/bgworker.sgml                  |  27 +++--
 src/backend/access/transam/parallel.c       |   1 -
 src/backend/postmaster/bgworker.c           | 128 +++++++++++---------
 src/backend/postmaster/postmaster.c         |   8 +-
 src/backend/replication/logical/launcher.c  |   2 -
 src/backend/storage/ipc/interrupt.c         |   3 +
 src/backend/storage/ipc/waiteventset.c      |   5 +
 src/include/postmaster/bgworker.h           |  10 +-
 src/include/postmaster/bgworker_internals.h |   4 +-
 src/test/modules/test_shm_mq/setup.c        |   3 +-
 src/test/modules/test_shm_mq/test_shm_mq.h  |   2 +
 src/test/modules/test_shm_mq/worker.c       |   9 +-
 src/test/modules/worker_spi/worker_spi.c    |   3 -
 14 files changed, 112 insertions(+), 99 deletions(-)

diff --git a/contrib/pg_prewarm/autoprewarm.c b/contrib/pg_prewarm/autoprewarm.c
index 65a423c7ddd..bfc7204082a 100644
--- a/contrib/pg_prewarm/autoprewarm.c
+++ b/contrib/pg_prewarm/autoprewarm.c
@@ -817,9 +817,6 @@ apw_start_leader_worker(void)
 		return;
 	}
 
-	/* must set notify PID to wait for startup */
-	worker.bgw_notify_pid = MyProcPid;
-
 	if (!RegisterDynamicBackgroundWorker(&worker, &handle))
 		ereport(ERROR,
 				(errcode(ERRCODE_INSUFFICIENT_RESOURCES),
@@ -853,9 +850,6 @@ apw_start_database_worker(void)
 	strcpy(worker.bgw_name, "autoprewarm worker");
 	strcpy(worker.bgw_type, "autoprewarm worker");
 
-	/* must set notify PID to wait for shutdown */
-	worker.bgw_notify_pid = MyProcPid;
-
 	if (!RegisterDynamicBackgroundWorker(&worker, &handle))
 		ereport(ERROR,
 				(errcode(ERRCODE_INSUFFICIENT_RESOURCES),
diff --git a/doc/src/sgml/bgworker.sgml b/doc/src/sgml/bgworker.sgml
index 3171054e55d..9e74651eb69 100644
--- a/doc/src/sgml/bgworker.sgml
+++ b/doc/src/sgml/bgworker.sgml
@@ -63,7 +63,7 @@ typedef struct BackgroundWorker
     char        bgw_function_name[BGW_MAXLEN];
     Datum       bgw_main_arg;
     char        bgw_extra[BGW_EXTRALEN];
-    pid_t       bgw_notify_pid;
+    pid_t       bgw_notify_pid;			/* not used */
 } BackgroundWorker;
 </programlisting>
   </para>
@@ -108,6 +108,18 @@ typedef struct BackgroundWorker
      </listitem>
     </varlistentry>
 
+    <varlistentry>
+     <term><literal>BGWORKER_NO_NOTIFY</literal></term>
+     <listitem>
+      <para>
+       <indexterm><primary>BGWORKER_NO_NOTIFY</primary></indexterm>
+       Normally, the backend that registers a dynamic worker will be notified
+       with <literal>INTERRUPT_GENERAL_WAKEUP</literal> when the workers state changes, which allows the
+       caller to wait for the worker to start and shut down.  That can be
+       suppressed by setting this flag.
+      </para>
+     </listitem>
+    </varlistentry>
    </variablelist>
 
   </para>
@@ -181,12 +193,8 @@ typedef struct BackgroundWorker
   </para>
 
   <para>
-   <structfield>bgw_notify_pid</structfield> is the PID of a PostgreSQL
-   backend process to which the postmaster should send <literal>SIGUSR1</literal>
-   when the process is started or exits.  It should be 0 for workers registered
-   at postmaster startup time, or when the backend registering the worker does
-   not wish to wait for the worker to start up.  Otherwise, it should be
-   initialized to <literal>MyProcPid</literal>.
+   <structfield>bgw_notify_pid</structfield> is not used and may be removed
+   in a future release.
   </para>
 
   <para>Once running, the process can connect to a database by calling
@@ -258,10 +266,7 @@ typedef struct BackgroundWorker
 
   <para>
    In some cases, a process which registers a background worker may wish to
-   wait for the worker to start up.  This can be accomplished by initializing
-   <structfield>bgw_notify_pid</structfield> to <literal>MyProcPid</literal> and
-   then passing the <type>BackgroundWorkerHandle *</type> obtained at
-   registration time to
+   wait for the worker to start up.  This can be accomplished with the
    <function>WaitForBackgroundWorkerStartup(<parameter>BackgroundWorkerHandle
    *handle</parameter>, <parameter>pid_t *</parameter>)</function> function.
    This function will block until the postmaster has attempted to start the
diff --git a/src/backend/access/transam/parallel.c b/src/backend/access/transam/parallel.c
index e1970ff9714..a8ba77cc379 100644
--- a/src/backend/access/transam/parallel.c
+++ b/src/backend/access/transam/parallel.c
@@ -600,7 +600,6 @@ LaunchParallelWorkers(ParallelContext *pcxt)
 	sprintf(worker.bgw_library_name, "postgres");
 	sprintf(worker.bgw_function_name, "ParallelWorkerMain");
 	worker.bgw_main_arg = UInt32GetDatum(dsm_segment_handle(pcxt->seg));
-	worker.bgw_notify_pid = MyProcPid;
 
 	/*
 	 * Start workers.
diff --git a/src/backend/postmaster/bgworker.c b/src/backend/postmaster/bgworker.c
index 9ed18f8407a..ca371ae66f0 100644
--- a/src/backend/postmaster/bgworker.c
+++ b/src/backend/postmaster/bgworker.c
@@ -78,6 +78,8 @@ typedef struct BackgroundWorkerSlot
 	pid_t		pid;			/* InvalidPid = not started yet; 0 = dead */
 	uint64		generation;		/* incremented when slot is recycled */
 	BackgroundWorker worker;
+	int			notify_pmchild;
+	ProcNumber	notify_proc_number;
 } BackgroundWorkerSlot;
 
 /*
@@ -192,8 +194,9 @@ BackgroundWorkerShmemInit(void)
 			slot->terminate = false;
 			slot->pid = InvalidPid;
 			slot->generation = 0;
+			slot->notify_pmchild = 0;
+			slot->notify_proc_number = INVALID_PROC_NUMBER;
 			rw->rw_shmem_slot = slotno;
-			rw->rw_worker.bgw_notify_pid = 0;	/* might be reinit after crash */
 			memcpy(&slot->worker, &rw->rw_worker, sizeof(BackgroundWorker));
 			++slotno;
 		}
@@ -234,6 +237,14 @@ FindRegisteredWorkerBySlotNumber(int slotno)
 	return NULL;
 }
 
+ProcNumber
+GetNotifyProcNumberForRegisteredWorker(RegisteredBgWorker *rw)
+{
+	BackgroundWorkerSlot *slot = &BackgroundWorkerData->slot[rw->rw_shmem_slot];
+
+	return slot->notify_proc_number;
+}
+
 /*
  * Notice changes to shared memory made by other backends.
  * Accept new worker requests only if allow_new_workers is true.
@@ -315,20 +326,20 @@ BackgroundWorkerStateChange(bool allow_new_workers)
 		/*
 		 * If the worker is marked for termination, we don't need to add it to
 		 * the registered workers list; we can just free the slot. However, if
-		 * bgw_notify_pid is set, the process that registered the worker may
-		 * need to know that we've processed the terminate request, so be sure
-		 * to signal it.
+		 * bgw_notify_proc_number is set, the process that registered the
+		 * worker may need to know that we've processed the terminate request,
+		 * so be sure to signal it.
 		 */
 		if (slot->terminate)
 		{
-			int			notify_pid;
+			int			notify_proc_number;
 
 			/*
 			 * We need a memory barrier here to make sure that the load of
-			 * bgw_notify_pid and the update of parallel_terminate_count
-			 * complete before the store to in_use.
+			 * bgw_notify_proc_number and the update of
+			 * parallel_terminate_count complete before the store to in_use.
 			 */
-			notify_pid = slot->worker.bgw_notify_pid;
+			notify_proc_number = slot->notify_proc_number;
 			if ((slot->worker.bgw_flags & BGWORKER_CLASS_PARALLEL) != 0)
 				BackgroundWorkerData->parallel_terminate_count++;
 			slot->pid = 0;
@@ -336,8 +347,8 @@ BackgroundWorkerStateChange(bool allow_new_workers)
 			pg_memory_barrier();
 			slot->in_use = false;
 
-			if (notify_pid != 0)
-				kill(notify_pid, SIGUSR1);
+			if (notify_proc_number != INVALID_PROC_NUMBER)
+				SendInterrupt(INTERRUPT_GENERAL_WAKEUP, notify_proc_number);
 
 			continue;
 		}
@@ -383,23 +394,6 @@ BackgroundWorkerStateChange(bool allow_new_workers)
 		rw->rw_worker.bgw_main_arg = slot->worker.bgw_main_arg;
 		memcpy(rw->rw_worker.bgw_extra, slot->worker.bgw_extra, BGW_EXTRALEN);
 
-		/*
-		 * Copy the PID to be notified about state changes, but only if the
-		 * postmaster knows about a backend with that PID.  It isn't an error
-		 * if the postmaster doesn't know about the PID, because the backend
-		 * that requested the worker could have died (or been killed) just
-		 * after doing so.  Nonetheless, at least until we get some experience
-		 * with how this plays out in the wild, log a message at a relative
-		 * high debug level.
-		 */
-		rw->rw_worker.bgw_notify_pid = slot->worker.bgw_notify_pid;
-		if (!PostmasterMarkPIDForWorkerNotify(rw->rw_worker.bgw_notify_pid))
-		{
-			elog(DEBUG1, "worker notification PID %d is not valid",
-				 (int) rw->rw_worker.bgw_notify_pid);
-			rw->rw_worker.bgw_notify_pid = 0;
-		}
-
 		/* Initialize postmaster bookkeeping. */
 		rw->rw_pid = 0;
 		rw->rw_crashed_at = 0;
@@ -421,7 +415,7 @@ BackgroundWorkerStateChange(bool allow_new_workers)
  * NOTE: The entry is unlinked from BackgroundWorkerList.  If the caller is
  * iterating through it, better use a mutable iterator!
  *
- * Caller is responsible for notifying bgw_notify_pid, if appropriate.
+ * Caller is responsible for notifying bgw_notify_proc_number, if appropriate.
  *
  * This function must be invoked only in the postmaster.
  */
@@ -466,8 +460,8 @@ ReportBackgroundWorkerPID(RegisteredBgWorker *rw)
 	slot = &BackgroundWorkerData->slot[rw->rw_shmem_slot];
 	slot->pid = rw->rw_pid;
 
-	if (rw->rw_worker.bgw_notify_pid != 0)
-		kill(rw->rw_worker.bgw_notify_pid, SIGUSR1);
+	if (slot->notify_proc_number != INVALID_PROC_NUMBER)
+		SendInterrupt(INTERRUPT_GENERAL_WAKEUP, slot->notify_proc_number);
 }
 
 /*
@@ -483,12 +477,12 @@ void
 ReportBackgroundWorkerExit(RegisteredBgWorker *rw)
 {
 	BackgroundWorkerSlot *slot;
-	int			notify_pid;
+	ProcNumber	notify_proc_number;
 
 	Assert(rw->rw_shmem_slot < max_worker_processes);
 	slot = &BackgroundWorkerData->slot[rw->rw_shmem_slot];
 	slot->pid = rw->rw_pid;
-	notify_pid = rw->rw_worker.bgw_notify_pid;
+	notify_proc_number = slot->notify_proc_number;
 
 	/*
 	 * If this worker is slated for deregistration, do that before notifying
@@ -501,27 +495,34 @@ ReportBackgroundWorkerExit(RegisteredBgWorker *rw)
 		rw->rw_worker.bgw_restart_time == BGW_NEVER_RESTART)
 		ForgetBackgroundWorker(rw);
 
-	if (notify_pid != 0)
-		kill(notify_pid, SIGUSR1);
+	if (notify_proc_number != INVALID_PROC_NUMBER)
+		SendInterrupt(INTERRUPT_GENERAL_WAKEUP, notify_proc_number);
 }
 
 /*
- * Cancel SIGUSR1 notifications for a PID belonging to an exiting backend.
+ * Cancel notifications for a PID belonging to an exiting backend.
  *
  * This function should only be called from the postmaster.
  */
 void
-BackgroundWorkerStopNotifications(pid_t pid)
+BackgroundWorkerStopNotifications(int pmchild)
 {
 	dlist_iter	iter;
 
 	dlist_foreach(iter, &BackgroundWorkerList)
 	{
 		RegisteredBgWorker *rw;
+		BackgroundWorkerSlot *slot;
 
 		rw = dlist_container(RegisteredBgWorker, rw_lnode, iter.cur);
-		if (rw->rw_worker.bgw_notify_pid == pid)
-			rw->rw_worker.bgw_notify_pid = 0;
+		Assert(rw->rw_shmem_slot < max_worker_processes);
+		slot = &BackgroundWorkerData->slot[rw->rw_shmem_slot];
+
+		if (slot->notify_pmchild == pmchild)
+		{
+			slot->notify_pmchild = 0;
+			slot->notify_proc_number = INVALID_PROC_NUMBER;
+		}
 	}
 }
 
@@ -553,14 +554,14 @@ ForgetUnstartedBackgroundWorkers(void)
 
 		/* If it's not yet started, and there's someone waiting ... */
 		if (slot->pid == InvalidPid &&
-			rw->rw_worker.bgw_notify_pid != 0)
+			slot->notify_proc_number != INVALID_PROC_NUMBER)
 		{
 			/* ... then zap it, and notify the waiter */
-			int			notify_pid = rw->rw_worker.bgw_notify_pid;
+			int			notify_proc_number = slot->notify_proc_number;
 
 			ForgetBackgroundWorker(rw);
-			if (notify_pid != 0)
-				kill(notify_pid, SIGUSR1);
+			if (notify_proc_number != INVALID_PROC_NUMBER)
+				SendInterrupt(INTERRUPT_GENERAL_WAKEUP, notify_proc_number);
 		}
 	}
 }
@@ -613,11 +614,6 @@ ResetBackgroundWorkerCrashTimes(void)
 			 * resetting.
 			 */
 			rw->rw_crashed_at = 0;
-
-			/*
-			 * If there was anyone waiting for it, they're history.
-			 */
-			rw->rw_worker.bgw_notify_pid = 0;
 		}
 	}
 }
@@ -981,15 +977,6 @@ RegisterBackgroundWorker(BackgroundWorker *worker)
 	if (!SanityCheckBackgroundWorker(worker, LOG))
 		return;
 
-	if (worker->bgw_notify_pid != 0)
-	{
-		ereport(LOG,
-				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-				 errmsg("background worker \"%s\": only dynamic background workers can request notification",
-						worker->bgw_name)));
-		return;
-	}
-
 	/*
 	 * Enforce maximum number of workers.  Note this is overly restrictive: we
 	 * could allow more non-shmem-connected workers, because these don't count
@@ -1105,6 +1092,25 @@ RegisterDynamicBackgroundWorker(BackgroundWorker *worker,
 			if (parallel)
 				BackgroundWorkerData->parallel_register_count++;
 
+			if ((slot->worker.bgw_flags & BGWORKER_SHMEM_ACCESS) != 0 &&
+				(slot->worker.bgw_flags & BGWORKER_NO_NOTIFY) == 0)
+			{
+				/*
+				 * Set notify_proc_number so that postmaster will send us an
+				 * interrupt. Also remember the pmchild slot number;
+				 * postmaster needs it to detect when we exit, to disarm the
+				 * notification.
+				 */
+				slot->notify_pmchild = MyPMChildSlot;
+				slot->notify_proc_number = MyProcNumber;
+			}
+			else
+			{
+				/* No notifications. */
+				slot->notify_pmchild = 0;
+				slot->notify_proc_number = INVALID_PROC_NUMBER;
+			}
+
 			/*
 			 * Make sure postmaster doesn't see the slot as in use before it
 			 * sees the new contents.
@@ -1205,8 +1211,9 @@ GetBackgroundWorkerPid(BackgroundWorkerHandle *handle, pid_t *pidp)
  * BGWH_POSTMASTER_DIED, since it that case we know that startup will not
  * take place.
  *
- * The caller *must* have set our PID as the worker's bgw_notify_pid,
- * else we will not be awoken promptly when the worker's state changes.
+ * This works only if the worker was registered with BGWORKER_SHMEM_ACCESS and
+ * without BGWORKER_NO_NOTIFY, else we will not be awoken promptly when the
+ * worker's state changes.
  */
 BgwHandleStatus
 WaitForBackgroundWorkerStartup(BackgroundWorkerHandle *handle, pid_t *pidp)
@@ -1250,8 +1257,9 @@ WaitForBackgroundWorkerStartup(BackgroundWorkerHandle *handle, pid_t *pidp)
  * up and return BGWH_POSTMASTER_DIED, because it's the postmaster that
  * notifies us when a worker's state changes.
  *
- * The caller *must* have set our PID as the worker's bgw_notify_pid,
- * else we will not be awoken promptly when the worker's state changes.
+ * This works only if the worker was registered with BGWORKER_SHMEM_ACCESS and
+ * without BGWORKER_NO_NOTIFY, else we will not be awoken promptly when the
+ * worker's state changes.
  */
 BgwHandleStatus
 WaitForBackgroundWorkerShutdown(BackgroundWorkerHandle *handle)
diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index 687c8e7672c..363bfe9d533 100644
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -3999,15 +3999,15 @@ maybe_start_bgworkers(void)
 		{
 			if (rw->rw_worker.bgw_restart_time == BGW_NEVER_RESTART)
 			{
-				int			notify_pid;
+				ProcNumber	notify_proc_number;
 
-				notify_pid = rw->rw_worker.bgw_notify_pid;
+				notify_proc_number = GetNotifyProcNumberForRegisteredWorker(rw);
 
 				ForgetBackgroundWorker(rw);
 
 				/* Report worker is gone now. */
-				if (notify_pid != 0)
-					kill(notify_pid, SIGUSR1);
+				if (notify_proc_number != INVALID_PROC_NUMBER)
+					SendInterrupt(INTERRUPT_GENERAL_WAKEUP, notify_proc_number);
 
 				continue;
 			}
diff --git a/src/backend/replication/logical/launcher.c b/src/backend/replication/logical/launcher.c
index 08525c8a84b..090b6b6a662 100644
--- a/src/backend/replication/logical/launcher.c
+++ b/src/backend/replication/logical/launcher.c
@@ -505,7 +505,6 @@ retry:
 	}
 
 	bgw.bgw_restart_time = BGW_NEVER_RESTART;
-	bgw.bgw_notify_pid = MyProcPid;
 	bgw.bgw_main_arg = Int32GetDatum(slot);
 
 	if (!RegisterDynamicBackgroundWorker(&bgw, &bgw_handle))
@@ -948,7 +947,6 @@ ApplyLauncherRegister(void)
 	snprintf(bgw.bgw_type, BGW_MAXLEN,
 			 "logical replication launcher");
 	bgw.bgw_restart_time = 5;
-	bgw.bgw_notify_pid = 0;
 	bgw.bgw_main_arg = (Datum) 0;
 
 	RegisterBackgroundWorker(&bgw);
diff --git a/src/backend/storage/ipc/interrupt.c b/src/backend/storage/ipc/interrupt.c
index b94ed343dc5..2191a9dabf8 100644
--- a/src/backend/storage/ipc/interrupt.c
+++ b/src/backend/storage/ipc/interrupt.c
@@ -98,6 +98,9 @@ RaiseInterrupt(InterruptType reason)
 
 /*
  * Set an interrupt flag in another backend.
+ *
+ * Note: This can also be called from the postmaster, so be careful to not
+ * trust the contents of shared memory.
  */
 void
 SendInterrupt(InterruptType reason, ProcNumber pgprocno)
diff --git a/src/backend/storage/ipc/waiteventset.c b/src/backend/storage/ipc/waiteventset.c
index 1bbba04e343..c208ecf529c 100644
--- a/src/backend/storage/ipc/waiteventset.c
+++ b/src/backend/storage/ipc/waiteventset.c
@@ -568,6 +568,11 @@ WakeupMyProc(void)
 void
 WakeupOtherProc(PGPROC *proc)
 {
+	/*
+	 * Note: This can also be called from the postmaster, so be careful to not
+	 * assume that the contents of shared memory are valid.  Reading the 'pid'
+	 * (or event handle on Windows) is safe enough.
+	 */
 #ifndef WIN32
 	kill(proc->pid, SIGURG);
 #else
diff --git a/src/include/postmaster/bgworker.h b/src/include/postmaster/bgworker.h
index 22fc49ec27f..8ad4a12728a 100644
--- a/src/include/postmaster/bgworker.h
+++ b/src/include/postmaster/bgworker.h
@@ -59,6 +59,14 @@
  */
 #define BGWORKER_BACKEND_DATABASE_CONNECTION		0x0002
 
+/*
+ * Dynamic workers created with shared memory access usually send an interrupt
+ * to the creating backend when they start and stop, allowing
+ * WaitForBackgroundWorker{Startup,Shutdown}() to work.  Such notifications
+ * can be suppressed with this flag.
+ */
+#define BGWORKER_NO_NOTIFY							0x0004
+
 /*
  * This class is used internally for parallel queries, to keep track of the
  * number of active parallel workers and make sure we never launch more than
@@ -97,7 +105,7 @@ typedef struct BackgroundWorker
 	char		bgw_function_name[BGW_MAXLEN];
 	Datum		bgw_main_arg;
 	char		bgw_extra[BGW_EXTRALEN];
-	pid_t		bgw_notify_pid; /* SIGUSR1 this backend on start/stop */
+	pid_t		bgw_notify_pid; /* not used */
 } BackgroundWorker;
 
 typedef enum BgwHandleStatus
diff --git a/src/include/postmaster/bgworker_internals.h b/src/include/postmaster/bgworker_internals.h
index f55adc85efc..db30e3fd6a8 100644
--- a/src/include/postmaster/bgworker_internals.h
+++ b/src/include/postmaster/bgworker_internals.h
@@ -15,6 +15,7 @@
 #include "datatype/timestamp.h"
 #include "lib/ilist.h"
 #include "postmaster/bgworker.h"
+#include "storage/procnumber.h"
 
 /* GUC options */
 
@@ -47,9 +48,10 @@ extern void BackgroundWorkerStateChange(bool allow_new_workers);
 extern void ForgetBackgroundWorker(RegisteredBgWorker *rw);
 extern void ReportBackgroundWorkerPID(RegisteredBgWorker *rw);
 extern void ReportBackgroundWorkerExit(RegisteredBgWorker *rw);
-extern void BackgroundWorkerStopNotifications(pid_t pid);
+extern void BackgroundWorkerStopNotifications(int pmchild);
 extern void ForgetUnstartedBackgroundWorkers(void);
 extern void ResetBackgroundWorkerCrashTimes(void);
+extern ProcNumber GetNotifyProcNumberForRegisteredWorker(RegisteredBgWorker *rw);
 
 /* Entry point for background worker processes */
 extern void BackgroundWorkerMain(char *startup_data, size_t startup_data_len) pg_attribute_noreturn();
diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c
index fa4c427943c..b3e4212fa2f 100644
--- a/src/test/modules/test_shm_mq/setup.c
+++ b/src/test/modules/test_shm_mq/setup.c
@@ -134,6 +134,7 @@ setup_dynamic_shared_memory(int64 queue_size, int nworkers,
 
 	/* Set up the header region. */
 	hdr = shm_toc_allocate(toc, sizeof(test_shm_mq_header));
+	hdr->leader_proc_number = MyProcNumber;
 	SpinLockInit(&hdr->mutex);
 	hdr->workers_total = nworkers;
 	hdr->workers_attached = 0;
@@ -223,8 +224,6 @@ setup_background_workers(int nworkers, dsm_segment *seg)
 	sprintf(worker.bgw_function_name, "test_shm_mq_main");
 	snprintf(worker.bgw_type, BGW_MAXLEN, "test_shm_mq");
 	worker.bgw_main_arg = UInt32GetDatum(dsm_segment_handle(seg));
-	/* set bgw_notify_pid, so we can detect if the worker stops */
-	worker.bgw_notify_pid = MyProcPid;
 
 	/* Register the workers. */
 	for (i = 0; i < nworkers; ++i)
diff --git a/src/test/modules/test_shm_mq/test_shm_mq.h b/src/test/modules/test_shm_mq/test_shm_mq.h
index 0ae7bd64cd0..7f27a61aff8 100644
--- a/src/test/modules/test_shm_mq/test_shm_mq.h
+++ b/src/test/modules/test_shm_mq/test_shm_mq.h
@@ -28,6 +28,8 @@
  */
 typedef struct
 {
+	ProcNumber	leader_proc_number;
+
 	slock_t		mutex;
 	int			workers_total;
 	int			workers_attached;
diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c
index 6fe9f9e4eb0..48f039131f6 100644
--- a/src/test/modules/test_shm_mq/worker.c
+++ b/src/test/modules/test_shm_mq/worker.c
@@ -53,7 +53,6 @@ test_shm_mq_main(Datum main_arg)
 	shm_mq_handle *outqh;
 	volatile test_shm_mq_header *hdr;
 	int			myworkernumber;
-	PGPROC	   *registrant;
 
 	/*
 	 * Establish signal handlers.
@@ -123,13 +122,7 @@ test_shm_mq_main(Datum main_arg)
 	SpinLockAcquire(&hdr->mutex);
 	++hdr->workers_ready;
 	SpinLockRelease(&hdr->mutex);
-	registrant = BackendPidGetProc(MyBgworkerEntry->bgw_notify_pid);
-	if (registrant == NULL)
-	{
-		elog(DEBUG1, "registrant backend has exited prematurely");
-		proc_exit(1);
-	}
-	SendInterrupt(INTERRUPT_GENERAL_WAKEUP, GetNumberFromPGProc(registrant));
+	SendInterrupt(INTERRUPT_GENERAL_WAKEUP, hdr->leader_proc_number);
 
 	/* Do the work. */
 	copy_messages(inqh, outqh);
diff --git a/src/test/modules/worker_spi/worker_spi.c b/src/test/modules/worker_spi/worker_spi.c
index 55febfb1b96..d60cfbc227b 100644
--- a/src/test/modules/worker_spi/worker_spi.c
+++ b/src/test/modules/worker_spi/worker_spi.c
@@ -376,7 +376,6 @@ _PG_init(void)
 	worker.bgw_restart_time = BGW_NEVER_RESTART;
 	sprintf(worker.bgw_library_name, "worker_spi");
 	sprintf(worker.bgw_function_name, "worker_spi_main");
-	worker.bgw_notify_pid = 0;
 
 	/*
 	 * Now fill in worker-specific data, and do the actual registrations.
@@ -425,8 +424,6 @@ worker_spi_launch(PG_FUNCTION_ARGS)
 	snprintf(worker.bgw_name, BGW_MAXLEN, "worker_spi dynamic worker %d", i);
 	snprintf(worker.bgw_type, BGW_MAXLEN, "worker_spi dynamic");
 	worker.bgw_main_arg = Int32GetDatum(i);
-	/* set bgw_notify_pid so that we can use WaitForBackgroundWorkerStartup */
-	worker.bgw_notify_pid = MyProcPid;
 
 	/* extract flags, if any */
 	ndim = ARR_NDIM(arr);
-- 
2.39.5

Reply via email to