From f7d3b3854ece45b2ba3b79643e99c1acbb09abae Mon Sep 17 00:00:00 2001
From: Karoline Pauls <code@karolinepauls.com>
Date: Wed, 8 May 2024 23:49:46 +0100
Subject: [PATCH] call pgstat_get_backend_current_activity once

---
 src/backend/storage/lmgr/deadlock.c         | 31 +++++++++++++--------
 src/backend/utils/activity/backend_status.c | 10 +++----
 src/include/utils/backend_status.h          |  4 ++-
 src/tools/pgindent/typedefs.list            |  1 +
 4 files changed, 29 insertions(+), 17 deletions(-)

diff --git a/src/backend/storage/lmgr/deadlock.c b/src/backend/storage/lmgr/deadlock.c
index d94f65df..c08f66af 100644
--- a/src/backend/storage/lmgr/deadlock.c
+++ b/src/backend/storage/lmgr/deadlock.c
@@ -1075,17 +1075,22 @@ DeadLockReport(void)
 	StringInfoData logbuf;		/* errdetail for server log */
 	StringInfoData locktagbuf;
 	int			i;
+	bool		isSuperuser = superuser();
+	LocalPgBackendCurrentActivity *activities = \
+		(LocalPgBackendCurrentActivity *) palloc(sizeof(LocalPgBackendCurrentActivity) * nDeadlockDetails);
 
 	initStringInfo(&clientbuf);
 	initStringInfo(&logbuf);
 	initStringInfo(&locktagbuf);
 
-	/* Generate the "waits for" lines sent to the client */
+	/* Generate the "waits for" lines sent to the client and the log */
 	for (i = 0; i < nDeadlockDetails; i++)
 	{
 		DEADLOCK_INFO *info = &deadlockDetails[i];
 		int			nextpid;
-		LocalPgBackendCurrentActivity activity = pgstat_get_backend_current_activity(info->pid, true);
+		const char *lockModeName = GetLockmodeName(info->locktag.locktag_lockmethodid, info->lockmode);
+
+		activities[i] = pgstat_get_backend_current_activity(info->pid);
 
 		/* The last proc waits for the first one... */
 		if (i < nDeadlockDetails - 1)
@@ -1104,29 +1109,33 @@ DeadLockReport(void)
 		appendStringInfo(&clientbuf,
 						 _("Process %d (application_name: %s) waits for %s on %s; blocked by process %d."),
 						 info->pid,
-						 activity.st_appname,
-						 GetLockmodeName(info->locktag.locktag_lockmethodid,
-										 info->lockmode),
+						 (activities[i].sameUser || isSuperuser) ? activities[i].st_appname : "<insufficient privilege>",
+						 lockModeName,
 						 locktagbuf.data,
 						 nextpid);
-	}
 
-	/* Duplicate all the above for the server ... */
-	appendBinaryStringInfo(&logbuf, clientbuf.data, clientbuf.len);
+		/* the difference is that we don't do user checking for the server log */
+		appendStringInfo(&logbuf,
+						 _("Process %d (application_name: %s) waits for %s on %s; blocked by process %d."),
+						 info->pid,
+						 activities[i].st_appname,
+						 lockModeName,
+						 locktagbuf.data,
+						 nextpid);
+	}
 
 	/* ... and add info about query strings */
 	for (i = 0; i < nDeadlockDetails; i++)
 	{
 		DEADLOCK_INFO *info = &deadlockDetails[i];
-		LocalPgBackendCurrentActivity activity = pgstat_get_backend_current_activity(info->pid, false);
 
 		appendStringInfoChar(&logbuf, '\n');
 
 		appendStringInfo(&logbuf,
 						 _("Process %d, (application_name: %s): %s"),
 						 info->pid,
-						 activity.st_appname,
-						 activity.st_activity);
+						 activities[i].st_appname,
+						 activities[i].st_activity);
 	}
 
 	pgstat_report_deadlock();
diff --git a/src/backend/utils/activity/backend_status.c b/src/backend/utils/activity/backend_status.c
index 1703aa79..6ccc76ae 100644
--- a/src/backend/utils/activity/backend_status.c
+++ b/src/backend/utils/activity/backend_status.c
@@ -882,11 +882,11 @@ pgstat_read_current_status(void)
  * ----------
  */
 struct LocalPgBackendCurrentActivity
-pgstat_get_backend_current_activity(int pid, bool checkUser)
+pgstat_get_backend_current_activity(int pid)
 {
 	PgBackendStatus *beentry;
 	int			i;
-	LocalPgBackendCurrentActivity activity = {"", "<backend information not available>"};
+	LocalPgBackendCurrentActivity activity = {"?", "<backend information not available>", false};
 
 	beentry = BackendStatusArray;
 	for (i = 1; i <= MaxBackends; i++)
@@ -926,9 +926,9 @@ pgstat_get_backend_current_activity(int pid, bool checkUser)
 		if (found)
 		{
 			/* Now it is safe to use the non-volatile pointer */
-			if (checkUser && !superuser() && beentry->st_userid != GetUserId())
-				activity.st_activity = "<insufficient privilege>";
-			else if (*(beentry->st_activity_raw) == '\0')
+			activity.sameUser = beentry->st_userid != GetUserId();
+
+			if (*(beentry->st_activity_raw) == '\0')
 				activity.st_activity = "<command string not enabled>";
 			else
 			{
diff --git a/src/include/utils/backend_status.h b/src/include/utils/backend_status.h
index a2110a8a..08d1b026 100644
--- a/src/include/utils/backend_status.h
+++ b/src/include/utils/backend_status.h
@@ -283,6 +283,8 @@ typedef struct LocalPgBackendCurrentActivity
 {
 	char	   *st_appname;
 	char	   *st_activity;
+	/* true if the activity user is the caller user */
+	bool		sameUser;
 } LocalPgBackendCurrentActivity;
 
 /* ----------
@@ -325,7 +327,7 @@ extern void pgstat_report_query_id(uint64 query_id, bool force);
 extern void pgstat_report_tempfile(size_t filesize);
 extern void pgstat_report_appname(const char *appname);
 extern void pgstat_report_xact_timestamp(TimestampTz tstamp);
-extern LocalPgBackendCurrentActivity pgstat_get_backend_current_activity(int pid, bool checkUser);
+extern LocalPgBackendCurrentActivity pgstat_get_backend_current_activity(int pid);
 extern const char *pgstat_get_crashed_backend_activity(int pid, char *buffer,
 													   int buflen);
 extern uint64 pgstat_get_my_query_id(void);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 2311f82d..f50c8935 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -1492,6 +1492,7 @@ ListenStmt
 LoInfo
 LoadStmt
 LocalBufferLookupEnt
+LocalPgBackendCurrentActivity
 LocalPgBackendStatus
 LocalTransactionId
 LocationIndex
-- 
2.34.1

