diff --git a/src/backend/port/unix_latch.c b/src/backend/port/unix_latch.c
index 335e9f66afb52163470ee9b69119b7fa16d2bc1c..bbd1810ea530547c75255f02c5be44c559cc03de 100644
--- a/src/backend/port/unix_latch.c
+++ b/src/backend/port/unix_latch.c
@@ -60,11 +60,41 @@ static volatile sig_atomic_t waiting = false;
 static int	selfpipe_readfd = -1;
 static int	selfpipe_writefd = -1;
 
-/* private function prototypes */
-static void initSelfPipe(void);
-static void drainSelfPipe(void);
+/* Private function prototypes */
 static void sendSelfPipeByte(void);
+static void drainSelfPipe(void);
+
+
+/*
+ * Initialize the process-local latch infrastructure.
+ *
+ * This must be called once during startup of any process that can wait on
+ * latches, before it issues any InitLatch() or OwnLatch() calls.
+ */
+void
+InitializeLatchSupport(void)
+{
+	int			pipefd[2];
+
+	Assert(selfpipe_readfd == -1);
+
+	/*
+	 * Set up the self-pipe that allows a signal handler to wake up the
+	 * select() in WaitLatch. Make the write-end non-blocking, so that
+	 * SetLatch won't block if the event has already been set many times
+	 * filling the kernel buffer. Make the read-end non-blocking too, so that
+	 * we can easily clear the pipe by reading until EAGAIN or EWOULDBLOCK.
+	 */
+	if (pipe(pipefd) < 0)
+		elog(FATAL, "pipe() failed: %m");
+	if (fcntl(pipefd[0], F_SETFL, O_NONBLOCK) < 0)
+		elog(FATAL, "fcntl() failed on read-end of self-pipe: %m");
+	if (fcntl(pipefd[1], F_SETFL, O_NONBLOCK) < 0)
+		elog(FATAL, "fcntl() failed on write-end of self-pipe: %m");
 
+	selfpipe_readfd = pipefd[0];
+	selfpipe_writefd = pipefd[1];
+}
 
 /*
  * Initialize a backend-local latch.
@@ -72,9 +102,8 @@ static void sendSelfPipeByte(void);
 void
 InitLatch(volatile Latch *latch)
 {
-	/* Initialize the self-pipe if this is our first latch in the process */
-	if (selfpipe_readfd == -1)
-		initSelfPipe();
+	/* Assert InitializeLatchSupport has been called in this process */
+	Assert(selfpipe_readfd >= 0);
 
 	latch->is_set = false;
 	latch->owner_pid = MyProcPid;
@@ -116,11 +145,10 @@ InitSharedLatch(volatile Latch *latch)
 void
 OwnLatch(volatile Latch *latch)
 {
-	Assert(latch->is_shared);
+	/* Assert InitializeLatchSupport has been called in this process */
+	Assert(selfpipe_readfd >= 0);
 
-	/* Initialize the self-pipe if this is our first latch in this process */
-	if (selfpipe_readfd == -1)
-		initSelfPipe();
+	Assert(latch->is_shared);
 
 	/* sanity check */
 	if (latch->owner_pid != 0)
@@ -514,30 +542,6 @@ latch_sigusr1_handler(void)
 		sendSelfPipeByte();
 }
 
-/* initialize the self-pipe */
-static void
-initSelfPipe(void)
-{
-	int			pipefd[2];
-
-	/*
-	 * Set up the self-pipe that allows a signal handler to wake up the
-	 * select() in WaitLatch. Make the write-end non-blocking, so that
-	 * SetLatch won't block if the event has already been set many times
-	 * filling the kernel buffer. Make the read-end non-blocking too, so that
-	 * we can easily clear the pipe by reading until EAGAIN or EWOULDBLOCK.
-	 */
-	if (pipe(pipefd) < 0)
-		elog(FATAL, "pipe() failed: %m");
-	if (fcntl(pipefd[0], F_SETFL, O_NONBLOCK) < 0)
-		elog(FATAL, "fcntl() failed on read-end of self-pipe: %m");
-	if (fcntl(pipefd[1], F_SETFL, O_NONBLOCK) < 0)
-		elog(FATAL, "fcntl() failed on write-end of self-pipe: %m");
-
-	selfpipe_readfd = pipefd[0];
-	selfpipe_writefd = pipefd[1];
-}
-
 /* Send one byte to the self-pipe, to wake up WaitLatch */
 static void
 sendSelfPipeByte(void)
diff --git a/src/backend/port/win32_latch.c b/src/backend/port/win32_latch.c
index 1f1ed33dc2d358ce27d7d769f4e6849d7d2d810d..0c089fc7ecc80b4c5fff806866ea6b8b46700ded 100644
--- a/src/backend/port/win32_latch.c
+++ b/src/backend/port/win32_latch.c
@@ -30,6 +30,12 @@
 #include "storage/shmem.h"
 
 
+void
+InitializeLatchSupport(void)
+{
+	/* currently, nothing to do here for Windows */
+}
+
 void
 InitLatch(volatile Latch *latch)
 {
diff --git a/src/backend/postmaster/pgarch.c b/src/backend/postmaster/pgarch.c
index d5d8be0587d663631e27886da66cdae71f8448db..a6c0aea3d6a957ee4f4a1652b82987f1d1aeae9f 100644
--- a/src/backend/postmaster/pgarch.c
+++ b/src/backend/postmaster/pgarch.c
@@ -234,8 +234,6 @@ PgArchiverMain(int argc, char *argv[])
 
 	MyProcPid = getpid();		/* reset MyProcPid */
 
-	InitLatch(&mainloop_latch); /* initialize latch used in main loop */
-
 	MyStartTime = time(NULL);	/* record Start Time for logging */
 
 	/*
@@ -247,6 +245,10 @@ PgArchiverMain(int argc, char *argv[])
 		elog(FATAL, "setsid() failed: %m");
 #endif
 
+	InitializeLatchSupport();		/* needed for latch waits */
+
+	InitLatch(&mainloop_latch); /* initialize latch used in main loop */
+
 	/*
 	 * Ignore all signals usually bound to some action in the postmaster,
 	 * except for SIGHUP, SIGTERM, SIGUSR1, SIGUSR2, and SIGQUIT.
diff --git a/src/backend/postmaster/pgstat.c b/src/backend/postmaster/pgstat.c
index 8389d5c4ae932a24d22a8d3fe20920a2bdede7c8..be3adf16d922039a636b59842f7b1b3f1440707d 100644
--- a/src/backend/postmaster/pgstat.c
+++ b/src/backend/postmaster/pgstat.c
@@ -3022,6 +3022,8 @@ PgstatCollectorMain(int argc, char *argv[])
 		elog(FATAL, "setsid() failed: %m");
 #endif
 
+	InitializeLatchSupport();		/* needed for latch waits */
+
 	/* Initialize private latch for use by signal handlers */
 	InitLatch(&pgStatLatch);
 
diff --git a/src/backend/postmaster/syslogger.c b/src/backend/postmaster/syslogger.c
index 0febf64d87f2b337b70e4c9e49d4399b6aa03c0e..cccec743b0d28922964acd5b597ed74548588856 100644
--- a/src/backend/postmaster/syslogger.c
+++ b/src/backend/postmaster/syslogger.c
@@ -251,6 +251,8 @@ SysLoggerMain(int argc, char *argv[])
 		elog(FATAL, "setsid() failed: %m");
 #endif
 
+	InitializeLatchSupport();		/* needed for latch waits */
+
 	/* Initialize private latch for use by signal handlers */
 	InitLatch(&sysLoggerLatch);
 
diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c
index 677042962a0e9e5723dc1fcf81d0cbb2f44446c2..5ae1506038cc59ebea9d6a7cee3ccebd3adc9819 100644
--- a/src/backend/storage/lmgr/proc.c
+++ b/src/backend/storage/lmgr/proc.c
@@ -279,6 +279,13 @@ InitProcess(void)
 	if (MyProc != NULL)
 		elog(ERROR, "you already exist");
 
+	/*
+	 * Initialize process-local latch support.  This could fail if the kernel
+	 * is low on resources, and if so we want to exit cleanly before acquiring
+	 * any shared-memory resources.
+	 */
+	InitializeLatchSupport();
+
 	/*
 	 * Try to get a proc struct from the free list.  If this fails, we must be
 	 * out of PGPROC structures (not to mention semaphores).
@@ -451,6 +458,13 @@ InitAuxiliaryProcess(void)
 	if (MyProc != NULL)
 		elog(ERROR, "you already exist");
 
+	/*
+	 * Initialize process-local latch support.  This could fail if the kernel
+	 * is low on resources, and if so we want to exit cleanly before acquiring
+	 * any shared-memory resources.
+	 */
+	InitializeLatchSupport();
+
 	/*
 	 * We use the ProcStructLock to protect assignment and releasing of
 	 * AuxiliaryProcs entries.
diff --git a/src/include/storage/latch.h b/src/include/storage/latch.h
index 71fb4868a000ccdd1afc6dd38bbbc8102c07f87f..f5c7fe1ca5ee9d0ee9706035f0b13f7a02bc1968 100644
--- a/src/include/storage/latch.h
+++ b/src/include/storage/latch.h
@@ -111,6 +111,7 @@ typedef struct
 /*
  * prototypes for functions in latch.c
  */
+extern void InitializeLatchSupport(void);
 extern void InitLatch(volatile Latch *latch);
 extern void InitSharedLatch(volatile Latch *latch);
 extern void OwnLatch(volatile Latch *latch);