From ee71da72c469ca7a4910a90c953deee5b0fd36ae Mon Sep 17 00:00:00 2001
From: Sehrope Sarkuni <sehrope@jackdb.com>
Date: Tue, 28 Jul 2026 15:24:13 +0000
Subject: [PATCH] Enlarge the syslogger pipe with F_SETPIPE_SZ

Backends block in write() once the syslogger pipe is full, so its
capacity bounds how far they can run ahead of the collector during a
burst.  The kernel default of 64 kB holds only sixteen maximum-size
chunks, which a handful of backends emitting multi-chunk messages can
exhaust immediately.

Ask for 1 MB when the pipe is created.  The request is capped by a
system limit and can fail, so retry with smaller sizes, stopping at the
capacity the kernel already gave the pipe to avoid shrinking it.  This
is best effort.  If F_GETPIPE_SZ or F_SETPIPE_SZ is unavailable, or no
request is accepted, the kernel default stands and behavior is
unchanged.  There is one such pipe per cluster, so the extra kernel
memory is bounded by that single buffer.
---
 src/backend/postmaster/syslogger.c | 31 ++++++++++++++++++++++++++++++
 1 file changed, 31 insertions(+)

diff --git a/src/backend/postmaster/syslogger.c b/src/backend/postmaster/syslogger.c
index b4b599c4c69..f0d07a9d293 100644
--- a/src/backend/postmaster/syslogger.c
+++ b/src/backend/postmaster/syslogger.c
@@ -60,6 +60,15 @@
  */
 #define READ_BUF_SIZE (2 * PIPE_CHUNK_SIZE)
 
+/*
+ * Capacity we ask the kernel for on the syslogger pipe.  Writers block once
+ * the pipe is full, so its capacity is what lets them run ahead of the
+ * syslogger across a burst.  The request is subject to a system limit and can
+ * fail, hence the retry with smaller values, stopping before we would shrink
+ * the pipe below the capacity the kernel already gave it.
+ */
+#define SYSLOGGER_PIPE_SIZE			(1024 * 1024)
+
 /* Log rotation signal file path, relative to $PGDATA */
 #define LOGROTATE_SIGNAL_FILE	"logrotate"
 
@@ -643,6 +652,28 @@ SysLogger_Start(int child_slot)
 			ereport(FATAL,
 					(errcode_for_socket_access(),
 					 errmsg("could not create pipe for syslog: %m")));
+
+#if defined(F_GETPIPE_SZ) && defined(F_SETPIPE_SZ)
+		/*
+		 * Best effort only.  Increase the pipe capacity where allowed, but
+		 * never reduce the capacity selected by the kernel.
+		 */
+		{
+			int			current_size;
+
+			current_size = fcntl(syslogPipe[0], F_GETPIPE_SZ);
+			if (current_size > 0)
+			{
+				for (int size = SYSLOGGER_PIPE_SIZE;
+					 size > current_size;
+					 size /= 2)
+				{
+					if (fcntl(syslogPipe[0], F_SETPIPE_SZ, size) >= 0)
+						break;
+				}
+			}
+		}
+#endif
 	}
 #else
 	if (!syslogPipe[0])
-- 
2.55.0

