Hi hackers,

While working on providing more informations related to locks (patch not shared
yet), it appeared that pg_blocking_pids() can omit the process that is actually
blocking a relation extension request.

Indeed, commit 85f6b49c2c53 made relation extension locks conflict between 
members
of the same parallel lock group, but did not update the same group filtering in
pg_blocking_pids().

The attached adds the relation extension exception in pg_blocking_pids().

pg_blocking_pids() reports parallel workers using their lock group leader PID.
Therefore, when one member of a parallel lock group blocks another, the PID
supplied to pg_blocking_pids() can appear in the result. This does not mean
that a process blocks itself. Rather, a lock held by one member of its parallel
lock group blocks a lock request made by another member of that group. The patch
documents this behavior.

No regression test is added because ensuring relation extension lock contention
between members of the same parallel lock group would be more complicated than
needed for this simple patch.

Regards,

-- 
Bertrand Drouvot
PostgreSQL Contributors Team
RDS Open Source Databases
Amazon Web Services: https://aws.amazon.com
>From a174547809a351d40bd48b226dd6bd8ec716083d Mon Sep 17 00:00:00 2001
From: Bertrand Drouvot <[email protected]>
Date: Sat, 29 Aug 2026 04:24:42 +0000
Subject: [PATCH v1] Report relation extension blockers within parallel lock
 groups in pg_blocking_pids()

Commit 85f6b49c2c53 made relation extension locks conflict between members of
the same parallel lock group, but did not update the same group filtering in
pg_blocking_pids(). So, pg_blocking_pids() can omit the process that is actually
blocking a relation extension request.

Add the relation extension exception in pg_blocking_pids().

pg_blocking_pids() reports parallel workers using their lock group leader PID.
Therefore, when one member of a parallel lock group blocks another, the PID
supplied to pg_blocking_pids() can appear in the result. This does not mean
that a process blocks itself. Rather, a lock held by one member of its parallel
lock group blocks a lock request made by another member of that group. The
commit also documents this behavior.

Author: Bertrand Drouvot <[email protected]>
Reviewed-by:
Discussion: https://postgr.es/m/...
---
 doc/src/sgml/func/func-info.sgml  | 14 +++++++++++---
 src/backend/utils/adt/lockfuncs.c | 10 ++++++++--
 2 files changed, 19 insertions(+), 5 deletions(-)
  68.7% doc/src/sgml/func/
  31.2% src/backend/utils/adt/

diff --git a/doc/src/sgml/func/func-info.sgml b/doc/src/sgml/func/func-info.sgml
index 2f03766b67a..226a815916d 100644
--- a/doc/src/sgml/func/func-info.sgml
+++ b/doc/src/sgml/func/func-info.sgml
@@ -246,9 +246,17 @@
         request and is ahead of it in the wait queue (soft block).  When using
         parallel queries the result always lists client-visible process IDs
         (that is, <function>pg_backend_pid</function> results) even if the
-        actual lock is held or awaited by a child worker process.  As a result
-        of that, there may be duplicated PIDs in the result.  Also note that
-        when a prepared transaction holds a conflicting lock, it will be
+        actual lock is held or awaited by a child worker process. As a result
+        of that, there may be duplicated PIDs in the result. When members of
+        the same parallel lock group block each other on a relation extension
+        lock (shown as lock type <literal>extend</literal> in <link
+        linkend="view-pg-locks"><structname>pg_locks</structname></link>), the
+        specified process ID can also appear in the result. This does not mean
+        that a process blocks itself. Rather, a lock held by one member of its
+        parallel lock group blocks a lock request made by another member of that
+        group.
+        Also note that when a prepared transaction holds a conflicting lock,
+        it will be
         represented by a zero process ID.
        </para>
        <para>
diff --git a/src/backend/utils/adt/lockfuncs.c b/src/backend/utils/adt/lockfuncs.c
index 3eb9a5b4215..1f0cc2b9bcb 100644
--- a/src/backend/utils/adt/lockfuncs.c
+++ b/src/backend/utils/adt/lockfuncs.c
@@ -518,8 +518,14 @@ pg_blocking_pids(PG_FUNCTION_ARGS)
 			/* A proc never blocks itself, so ignore that entry */
 			if (instance == blocked_instance)
 				continue;
-			/* Members of same lock group never block each other, either */
-			if (instance->leaderPid == blocked_instance->leaderPid)
+
+			/*
+			 * Members of the same lock group do not block each other, except
+			 * when extending a relation.
+			 */
+			if (instance->leaderPid == blocked_instance->leaderPid &&
+				blocked_instance->locktag.locktag_type !=
+				LOCKTAG_RELATION_EXTEND)
 				continue;
 
 			if (conflictMask & instance->holdMask)
-- 
2.34.1

Reply via email to