I propose a little refactoring, attached, to replace the "isRegularBackend" field in PGPROC with full "backendType".

Andres briefly suggested this a while back [1]:

On Fri, 22 Nov 2024 at 22:13, Andres Freund <andres(at)anarazel(dot)de> wrote:
Or we could have a copy of the backend type in PGPROC.

but we didn't follow up on that approach. I don't see why, it seems so much simpler than what we ended up doing. Am I missing something?

[1] https://www.postgresql.org/message-id/ujenaa2uabzfkwxwmfifawzdozh3ljr7geozlhftsuosgm7n7q%40g3utqqyyosb6

- Heikki
From 3a9746bbb1a6b015c30b59ebf15ee16470fb3e4f Mon Sep 17 00:00:00 2001
From: Heikki Linnakangas <[email protected]>
Date: Tue, 3 Feb 2026 22:53:14 +0200
Subject: [PATCH 1/1] Add backendType to PGPROC, replacing isRegularBackend

We can immediately make use of it in pg_signal_backend(), which was
previously fetching the process type from the backend status array (by
pgstat_get_backend_type_by_proc_number()). That was correct but felt a
little questionable to me: backend status should be for observability
purposes only, not for permission checks.
---
 src/backend/access/transam/twophase.c       |  2 +-
 src/backend/storage/ipc/procarray.c         |  4 ++--
 src/backend/storage/ipc/signalfuncs.c       |  5 +----
 src/backend/storage/lmgr/proc.c             |  4 ++--
 src/backend/utils/activity/backend_status.c | 25 ---------------------
 src/include/storage/proc.h                  |  5 +++--
 src/include/utils/backend_status.h          |  1 -
 7 files changed, 9 insertions(+), 37 deletions(-)

diff --git a/src/backend/access/transam/twophase.c b/src/backend/access/transam/twophase.c
index 601ce3faa64..eabc4d48208 100644
--- a/src/backend/access/transam/twophase.c
+++ b/src/backend/access/transam/twophase.c
@@ -470,7 +470,7 @@ MarkAsPreparingGuts(GlobalTransaction gxact, FullTransactionId fxid,
 	proc->databaseId = databaseid;
 	proc->roleId = owner;
 	proc->tempNamespaceId = InvalidOid;
-	proc->isRegularBackend = false;
+	proc->backendType = B_INVALID;
 	proc->lwWaiting = LW_WS_NOT_WAITING;
 	proc->lwWaitMode = 0;
 	proc->waitLock = NULL;
diff --git a/src/backend/storage/ipc/procarray.c b/src/backend/storage/ipc/procarray.c
index 748c06b51cb..301f54fb5a8 100644
--- a/src/backend/storage/ipc/procarray.c
+++ b/src/backend/storage/ipc/procarray.c
@@ -3589,7 +3589,7 @@ CountDBConnections(Oid databaseid)
 
 		if (proc->pid == 0)
 			continue;			/* do not count prepared xacts */
-		if (!proc->isRegularBackend)
+		if (proc->backendType != B_BACKEND)
 			continue;			/* count only regular backend processes */
 		if (!OidIsValid(databaseid) ||
 			proc->databaseId == databaseid)
@@ -3660,7 +3660,7 @@ CountUserBackends(Oid roleid)
 
 		if (proc->pid == 0)
 			continue;			/* do not count prepared xacts */
-		if (!proc->isRegularBackend)
+		if (proc->backendType != B_BACKEND)
 			continue;			/* count only regular backend processes */
 		if (proc->roleId == roleid)
 			count++;
diff --git a/src/backend/storage/ipc/signalfuncs.c b/src/backend/storage/ipc/signalfuncs.c
index 6f7759cd720..d48b4fe3799 100644
--- a/src/backend/storage/ipc/signalfuncs.c
+++ b/src/backend/storage/ipc/signalfuncs.c
@@ -87,10 +87,7 @@ pg_signal_backend(int pid, int sig)
 	 */
 	if (!OidIsValid(proc->roleId) || superuser_arg(proc->roleId))
 	{
-		ProcNumber	procNumber = GetNumberFromPGProc(proc);
-		BackendType backendType = pgstat_get_backend_type_by_proc_number(procNumber);
-
-		if (backendType == B_AUTOVAC_WORKER)
+		if (proc->backendType == B_AUTOVAC_WORKER)
 		{
 			if (!has_privs_of_role(GetUserId(), ROLE_PG_SIGNAL_AUTOVACUUM_WORKER))
 				return SIGNAL_BACKEND_NOAUTOVAC;
diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c
index fdeed0f3953..1301269ec61 100644
--- a/src/backend/storage/lmgr/proc.c
+++ b/src/backend/storage/lmgr/proc.c
@@ -486,7 +486,7 @@ InitProcess(void)
 	MyProc->databaseId = InvalidOid;
 	MyProc->roleId = InvalidOid;
 	MyProc->tempNamespaceId = InvalidOid;
-	MyProc->isRegularBackend = AmRegularBackendProcess();
+	MyProc->backendType = MyBackendType;
 	MyProc->delayChkptFlags = 0;
 	MyProc->statusFlags = 0;
 	/* NB -- autovac launcher intentionally does not set IS_AUTOVACUUM */
@@ -684,7 +684,7 @@ InitAuxiliaryProcess(void)
 	MyProc->databaseId = InvalidOid;
 	MyProc->roleId = InvalidOid;
 	MyProc->tempNamespaceId = InvalidOid;
-	MyProc->isRegularBackend = false;
+	MyProc->backendType = B_INVALID;
 	MyProc->delayChkptFlags = 0;
 	MyProc->statusFlags = 0;
 	MyProc->lwWaiting = LW_WS_NOT_WAITING;
diff --git a/src/backend/utils/activity/backend_status.c b/src/backend/utils/activity/backend_status.c
index c84e6536580..cd087129469 100644
--- a/src/backend/utils/activity/backend_status.c
+++ b/src/backend/utils/activity/backend_status.c
@@ -1164,31 +1164,6 @@ pgstat_get_my_plan_id(void)
 	return MyBEEntry->st_plan_id;
 }
 
-/* ----------
- * pgstat_get_backend_type_by_proc_number() -
- *
- *	Return the type of the backend with the specified ProcNumber.  This looks
- *	directly at the BackendStatusArray, so the return value may be out of date.
- *	The only current use of this function is in pg_signal_backend(), which is
- *	inherently racy, so we don't worry too much about this.
- *
- *	It is the caller's responsibility to use this wisely; at minimum, callers
- *	should ensure that procNumber is valid and perform the required permissions
- *	checks.
- * ----------
- */
-BackendType
-pgstat_get_backend_type_by_proc_number(ProcNumber procNumber)
-{
-	volatile PgBackendStatus *status = &BackendStatusArray[procNumber];
-
-	/*
-	 * We bypass the changecount mechanism since fetching and storing an int
-	 * is almost certainly atomic.
-	 */
-	return status->st_backendType;
-}
-
 /* ----------
  * cmp_lbestatus
  *
diff --git a/src/include/storage/proc.h b/src/include/storage/proc.h
index 81f1960a635..930b89fc9ea 100644
--- a/src/include/storage/proc.h
+++ b/src/include/storage/proc.h
@@ -17,6 +17,7 @@
 #include "access/clog.h"
 #include "access/xlogdefs.h"
 #include "lib/ilist.h"
+#include "miscadmin.h"
 #include "storage/latch.h"
 #include "storage/lock.h"
 #include "storage/pg_sema.h"
@@ -166,7 +167,7 @@ typedef enum
  * but its myProcLocks[] lists are valid.
  *
  * We allow many fields of this struct to be accessed without locks, such as
- * delayChkptFlags and isRegularBackend. However, keep in mind that writing
+ * delayChkptFlags, and backendType. However, keep in mind that writing
  * mirrored ones (see below) requires holding ProcArrayLock or XidGenLock in
  * at least shared mode, so that pgxactoff does not change concurrently.
  *
@@ -233,7 +234,7 @@ struct PGPROC
 	Oid			tempNamespaceId;	/* OID of temp schema this backend is
 									 * using */
 
-	bool		isRegularBackend;	/* true if it's a regular backend. */
+	BackendType backendType;	/* what kind of process is this? */
 
 	/*
 	 * Info about LWLock the process is currently waiting for, if any.
diff --git a/src/include/utils/backend_status.h b/src/include/utils/backend_status.h
index 781e48c0c10..ddd06304e97 100644
--- a/src/include/utils/backend_status.h
+++ b/src/include/utils/backend_status.h
@@ -331,7 +331,6 @@ extern const char *pgstat_get_crashed_backend_activity(int pid, char *buffer,
 													   int buflen);
 extern int64 pgstat_get_my_query_id(void);
 extern int64 pgstat_get_my_plan_id(void);
-extern BackendType pgstat_get_backend_type_by_proc_number(ProcNumber procNumber);
 
 
 /* ----------
-- 
2.47.3

Reply via email to