aboutsummaryrefslogtreecommitdiff
path: root/src/backend
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend')
-rw-r--r--src/backend/port/unix_latch.c72
-rw-r--r--src/backend/port/win32_latch.c6
-rw-r--r--src/backend/postmaster/pgarch.c6
-rw-r--r--src/backend/postmaster/pgstat.c2
-rw-r--r--src/backend/postmaster/syslogger.c2
-rw-r--r--src/backend/storage/lmgr/proc.c14
6 files changed, 66 insertions, 36 deletions
diff --git a/src/backend/port/unix_latch.c b/src/backend/port/unix_latch.c
index 65b2fc56e03..343bf5e536b 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)
@@ -511,30 +539,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 eb46dcad1ba..eaa30c4a501 100644
--- a/src/backend/port/win32_latch.c
+++ b/src/backend/port/win32_latch.c
@@ -31,6 +31,12 @@
void
+InitializeLatchSupport(void)
+{
+ /* currently, nothing to do here for Windows */
+}
+
+void
InitLatch(volatile Latch *latch)
{
latch->is_set = false;
diff --git a/src/backend/postmaster/pgarch.c b/src/backend/postmaster/pgarch.c
index 5c43cdde653..d87618f7621 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 73d5b2e39c8..7684e11a9ae 100644
--- a/src/backend/postmaster/pgstat.c
+++ b/src/backend/postmaster/pgstat.c
@@ -3021,6 +3021,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 98e0bfbf615..eeba40b928a 100644
--- a/src/backend/postmaster/syslogger.c
+++ b/src/backend/postmaster/syslogger.c
@@ -250,6 +250,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 8593713e78f..1dda2f81c30 100644
--- a/src/backend/storage/lmgr/proc.c
+++ b/src/backend/storage/lmgr/proc.c
@@ -292,6 +292,13 @@ InitProcess(void)
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).
*
@@ -465,6 +472,13 @@ InitAuxiliaryProcess(void)
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.
*