diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml
index cb0a36a170f..e1e3d32744c 100644
--- a/doc/src/sgml/func.sgml
+++ b/doc/src/sgml/func.sgml
@@ -15952,10 +15952,11 @@ SET search_path TO <replaceable>schema</> <optional>, <replaceable>schema</>, ..
     <function>pg_blocking_pids</function> returns an array of the process IDs
     of the sessions that are blocking the server process with the specified
     process ID, or an empty array if there is no such server process or it is
-    not blocked.  One server process blocks another if it either holds a lock
-    that conflicts with the blocked process's lock request (hard block), or is
+    not blocked.  One server process blocks another if it holds a lock that
+    conflicts with the blocked process's lock request (hard block), is
     waiting for a lock that would conflict with the blocked process's lock
-    request and is ahead of it in the wait queue (soft block).  When using
+    request and is ahead of it in the wait queue (soft block), or potentially
+    conflicts with a SERIALIZABLE DEFERRABLE transaction.  When using
     parallel queries the result always lists client-visible process IDs (that
     is, <function>pg_backend_pid</> results) even if the actual lock is held
     or awaited by a child worker process.  As a result of that, there may be
diff --git a/src/backend/storage/lmgr/predicate.c b/src/backend/storage/lmgr/predicate.c
index 7aa719d6123..3283ed68c81 100644
--- a/src/backend/storage/lmgr/predicate.c
+++ b/src/backend/storage/lmgr/predicate.c
@@ -1549,6 +1549,53 @@ GetSafeSnapshot(Snapshot origSnapshot)
 }
 
 /*
+ * If the given process is currently blocked in GetSafeSnapshot, return the
+ * list of process IDs that it is waiting for.  This is intended for testing
+ * and is used by pg_blocking_pids().
+ */
+List *
+GetSafeSnapshotBlockingPids(int blocked_pid)
+{
+	SERIALIZABLEXACT *sxact;
+	List	   *blocking_pids = NIL;
+
+	LWLockAcquire(SerializableXactHashLock, LW_SHARED);
+
+	/* Find blocked_pid's SERIALIZABLEXACT by linear search. */
+	for (sxact = FirstPredXact(); sxact != NULL; sxact = NextPredXact(sxact))
+	{
+		if (sxact->pid == blocked_pid)
+			break;
+	}
+
+	/* Did we find it, and is it currently waiting in GetSafeSnapshot? */
+	if (sxact != NULL && (sxact->flags & SXACT_FLAG_DEFERRABLE_WAITING) != 0)
+	{
+		RWConflict possibleUnsafeConflict;
+
+		/* Traverse the list of possible unsafe conflicts collecting PIDs. */
+		possibleUnsafeConflict = (RWConflict)
+			SHMQueueNext(&sxact->possibleUnsafeConflicts,
+						 &sxact->possibleUnsafeConflicts,
+						 offsetof(RWConflictData, inLink));
+
+		while (possibleUnsafeConflict != NULL)
+		{
+			blocking_pids = lappend_int(blocking_pids,
+										possibleUnsafeConflict->sxactIn->pid);
+			possibleUnsafeConflict = (RWConflict)
+				SHMQueueNext(&sxact->possibleUnsafeConflicts,
+							 &possibleUnsafeConflict->inLink,
+							 offsetof(RWConflictData, inLink));
+		}
+	}
+
+	LWLockRelease(SerializableXactHashLock);
+
+	return blocking_pids;
+}
+
+/*
  * Acquire a snapshot that can be used for the current transaction.
  *
  * Make sure we have a SERIALIZABLEXACT reference in MySerializableXact.
diff --git a/src/backend/utils/adt/lockfuncs.c b/src/backend/utils/adt/lockfuncs.c
index 63f956e6708..6593b27a00c 100644
--- a/src/backend/utils/adt/lockfuncs.c
+++ b/src/backend/utils/adt/lockfuncs.c
@@ -17,6 +17,7 @@
 #include "catalog/pg_type.h"
 #include "funcapi.h"
 #include "miscadmin.h"
+#include "nodes/pg_list.h"
 #include "storage/predicate_internals.h"
 #include "utils/array.h"
 #include "utils/builtins.h"
@@ -412,7 +413,8 @@ pg_lock_status(PG_FUNCTION_ARGS)
  * because multiple blockers have same group leader PID).  We do not bother
  * to eliminate such duplicates from the result.
  *
- * We need not consider predicate locks here, since those don't block anything.
+ * We need not consider predicate locks here, since those don't block anything,
+ * but we do consider backends blocked in GetSafeSnapshot.
  */
 Datum
 pg_blocking_pids(PG_FUNCTION_ARGS)
@@ -421,16 +423,29 @@ pg_blocking_pids(PG_FUNCTION_ARGS)
 	Datum	   *arrayelems;
 	int			narrayelems;
 	BlockedProcsData *lockData; /* state data from lmgr */
+	List	   *snapshotBlockers;
+	ListCell   *lc;
 	int			i,
 				j;
 
 	/* Collect a snapshot of lock manager state */
 	lockData = GetBlockerStatusData(blocked_pid);
 
-	/* We can't need more output entries than there are reported PROCLOCKs */
-	arrayelems = (Datum *) palloc(lockData->nlocks * sizeof(Datum));
+	/* Collect a snapshot of processes waited for by GetSafeSnapshot */
+	snapshotBlockers = GetSafeSnapshotBlockingPids(blocked_pid);
+
+	/*
+	 * We can't need more output entries than there are reported PROCLOCKs,
+	 * plus any snapshot blockers.
+	 */
+	arrayelems = (Datum *)
+		palloc((lockData->nlocks + list_length(snapshotBlockers)) * sizeof(Datum));
 	narrayelems = 0;
 
+	/* Add any blockers of GetSafeSnapshot */
+	foreach(lc, snapshotBlockers)
+		arrayelems[narrayelems++] = lfirst_int(lc);
+
 	/* For each blocked proc in the lock group ... */
 	for (i = 0; i < lockData->nprocs; i++)
 	{
@@ -508,7 +523,7 @@ pg_blocking_pids(PG_FUNCTION_ARGS)
 	}
 
 	/* Assert we didn't overrun arrayelems[] */
-	Assert(narrayelems <= lockData->nlocks);
+	Assert(narrayelems <= (lockData->nlocks + list_length(snapshotBlockers)));
 
 	/* Construct array, using hardwired knowledge about int4 type */
 	PG_RETURN_ARRAYTYPE_P(construct_array(arrayelems, narrayelems,
diff --git a/src/include/storage/predicate_internals.h b/src/include/storage/predicate_internals.h
index 408d94cc7a5..e9527aedc0b 100644
--- a/src/include/storage/predicate_internals.h
+++ b/src/include/storage/predicate_internals.h
@@ -474,5 +474,6 @@ typedef struct TwoPhasePredicateRecord
  * locking internals.
  */
 extern PredicateLockData *GetPredicateLockStatusData(void);
+extern List *GetSafeSnapshotBlockingPids(int blocked_pid);
 
 #endif   /* PREDICATE_INTERNALS_H */
diff --git a/src/test/isolation/isolationtester.c b/src/test/isolation/isolationtester.c
index 4d18710bdfd..f77f4657512 100644
--- a/src/test/isolation/isolationtester.c
+++ b/src/test/isolation/isolationtester.c
@@ -231,14 +231,6 @@ main(int argc, char **argv)
 		appendPQExpBuffer(&wait_query, ",%s", backend_pids[i]);
 	appendPQExpBufferStr(&wait_query, "}'::integer[]");
 
-	/* Also detect certain wait events. */
-	appendPQExpBufferStr(&wait_query,
-						 " OR EXISTS ("
-						 "  SELECT * "
-						 "  FROM pg_catalog.pg_stat_activity "
-						 "  WHERE pid = $1 "
-						 "  AND wait_event IN ('SafeSnapshot'))");
-
 	res = PQprepare(conns[0], PREP_WAITING, wait_query.data, 0, NULL);
 	if (PQresultStatus(res) != PGRES_COMMAND_OK)
 	{
