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