From dbdbd2dad1d449b1d23af3a1e5414077af0f194c Mon Sep 17 00:00:00 2001
From: shihao zhong <zhong950419@gmail.com>
Date: Wed, 14 Oct 2026 08:22:27 -0400
Subject: [PATCH v2 1/2] Absorb ProcSignalBarriers while waiting for the client

A backend blocked writing to or reading from a client that stopped
responding never absorbed barriers, so promotion, standby replay and
DROP DATABASE waited for it without limit.  Absorb them in that wait.
We may be in the middle of a message, so make any error FATAL.

Diagnosed-by: Manuel Reyes Bravo <manuelreyesbravo@gmail.com>
---
 src/backend/tcop/postgres.c | 32 ++++++++++++++++++++++++++++++++
 1 file changed, 32 insertions(+)

diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index b6bdfe213fe..0c5fcd9db92 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -502,6 +502,34 @@ ReadCommand(StringInfo inBuf)
 	return result;
 }
 
+/*
+ * Absorb ProcSignalBarriers while blocked on a client read or write, so that
+ * a client that stops sending or reading can't hold up the processes waiting
+ * for them.  We might be in the middle of a protocol message, so make any
+ * error FATAL and don't send it to the client.
+ */
+static void
+ProcessClientBarrierInterrupt(void)
+{
+	bool		save_ExitOnAnyError;
+	CommandDest save_whereToSendOutput;
+
+	if (!ProcSignalBarrierPending ||
+		InterruptHoldoffCount != 0 || CritSectionCount != 0)
+		return;
+
+	save_ExitOnAnyError = ExitOnAnyError;
+	save_whereToSendOutput = whereToSendOutput;
+	ExitOnAnyError = true;
+	if (whereToSendOutput == DestRemote)
+		whereToSendOutput = DestNone;
+
+	ProcessProcSignalBarrier();
+
+	ExitOnAnyError = save_ExitOnAnyError;
+	whereToSendOutput = save_whereToSendOutput;
+}
+
 /*
  * ProcessClientReadInterrupt() - Process interrupts specific to client reads
  *
@@ -544,6 +572,8 @@ ProcessClientReadInterrupt(bool blocked)
 		else
 			SetLatch(MyLatch);
 	}
+	else if (blocked)
+		ProcessClientBarrierInterrupt();
 
 	errno = save_errno;
 }
@@ -596,6 +626,8 @@ ProcessClientWriteInterrupt(bool blocked)
 		else
 			SetLatch(MyLatch);
 	}
+	else if (blocked)
+		ProcessClientBarrierInterrupt();
 
 	errno = save_errno;
 }
-- 
2.37.1 (Apple Git-137.1)

