0001-Use-signals-for-postmaster-death-on-Linux-v3.patch
application/octet-stream
Filename: 0001-Use-signals-for-postmaster-death-on-Linux-v3.patch
Type: application/octet-stream
Part: 0
Patch
Format: format-patch
Series: patch v3-0001
Subject: Use signals for postmaster death on Linux.
| File | + | − |
|---|---|---|
| configure | 40 | 0 |
| configure.in | 22 | 0 |
| src/backend/postmaster/postmaster.c | 2 | 0 |
| src/backend/storage/ipc/latch.c | 3 | 3 |
| src/backend/storage/ipc/pmsignal.c | 54 | 1 |
| src/include/c.h | 11 | 0 |
| src/include/pg_config.h.in | 3 | 0 |
| src/include/storage/pmsignal.h | 16 | 1 |
From c1cf4c743597a776fbbd50a276a4177ad4e5a34b Mon Sep 17 00:00:00 2001
From: Thomas Munro <munro@ip9.org>
Date: Wed, 18 Apr 2018 00:59:39 +0100
Subject: [PATCH 1/2] Use signals for postmaster death on Linux.
Linux provides a way to ask for a signal when your parent process dies. Use
that to make PostmasterIsAlive() very cheap.
Author: Thomas Munro, based on a suggestion from Andres Freund
Discussion: https://postgr.es/m/7261eb39-0369-f2f4-1bb5-62f3b6083b5e%40iki.fi
https://postgr.es/m/20180411002643.6buofht4ranhei7k%40alap3.anarazel.de
---
configure | 40 +++++++++++++++++++++++++++
configure.in | 22 +++++++++++++++
src/backend/postmaster/postmaster.c | 2 ++
src/backend/storage/ipc/latch.c | 6 ++--
src/backend/storage/ipc/pmsignal.c | 55 ++++++++++++++++++++++++++++++++++++-
src/include/c.h | 11 ++++++++
src/include/pg_config.h.in | 3 ++
src/include/storage/pmsignal.h | 17 +++++++++++-
8 files changed, 151 insertions(+), 5 deletions(-)
diff --git a/configure b/configure
index 56f18dfbc26..29ba38ee174 100755
--- a/configure
+++ b/configure
@@ -9717,6 +9717,46 @@ program to use during the build." "$LINENO" 5
fi
fi
+#
+# Signals to detect parent process death
+#
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for parent death signal support" >&5
+$as_echo_n "checking for parent death signal support... " >&6; }
+
+# Linux has prctl(PR_SET_PDEATHSIG, ...)
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+#include <sys/prctl.h>
+
+int
+main ()
+{
+
+#ifndef PR_SET_PDEATHSIG
+#error PR_SET_PDEATHSIG not defined
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ HAVE_PR_SET_PDEATHSIG=1
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+if test x"$HAVE_PR_SET_PDEATHSIG" = "x1"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: PR_SET_PDEATHSIG" >&5
+$as_echo "PR_SET_PDEATHSIG" >&6; }
+
+$as_echo "#define HAVE_PR_SET_PDEATHSIG 1" >>confdefs.h
+
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
#
# Pthreads
#
diff --git a/configure.in b/configure.in
index da02a56ec66..31dda503628 100644
--- a/configure.in
+++ b/configure.in
@@ -1022,6 +1022,28 @@ program to use during the build.])
fi
fi
+#
+# Signals to detect parent process death
+#
+AC_MSG_CHECKING([for parent death signal support])
+
+# Linux has prctl(PR_SET_PDEATHSIG, ...)
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([
+#include <sys/prctl.h>
+], [
+#ifndef PR_SET_PDEATHSIG
+#error PR_SET_PDEATHSIG not defined
+#endif
+])], [HAVE_PR_SET_PDEATHSIG=1])
+
+if test x"$HAVE_PR_SET_PDEATHSIG" = "x1"; then
+ AC_MSG_RESULT(PR_SET_PDEATHSIG)
+ AC_DEFINE(HAVE_PR_SET_PDEATHSIG, 1,
+ [Define to 1 if the system supports PR_SET_PDEATHSIG])
+else
+ AC_MSG_RESULT(no)
+fi
+
#
# Pthreads
#
diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index d948369f3ea..c3ef7ee38ca 100644
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -2484,6 +2484,8 @@ ClosePostmasterPorts(bool am_syslogger)
if (bonjour_sdref)
close(DNSServiceRefSockFD(bonjour_sdref));
#endif
+
+ PostmasterDeathInit();
}
diff --git a/src/backend/storage/ipc/latch.c b/src/backend/storage/ipc/latch.c
index e6706f7fb80..f6dda9cc9ac 100644
--- a/src/backend/storage/ipc/latch.c
+++ b/src/backend/storage/ipc/latch.c
@@ -1112,7 +1112,7 @@ WaitEventSetWaitBlock(WaitEventSet *set, int cur_timeout,
* WL_POSTMASTER_DEATH event would be painful. Re-checking doesn't
* cost much.
*/
- if (!PostmasterIsAlive())
+ if (!PostmasterIsAliveInternal())
{
occurred_events->fd = PGINVALID_SOCKET;
occurred_events->events = WL_POSTMASTER_DEATH;
@@ -1230,7 +1230,7 @@ WaitEventSetWaitBlock(WaitEventSet *set, int cur_timeout,
* WL_POSTMASTER_DEATH event would be painful. Re-checking doesn't
* cost much.
*/
- if (!PostmasterIsAlive())
+ if (!PostmasterIsAliveInternal())
{
occurred_events->fd = PGINVALID_SOCKET;
occurred_events->events = WL_POSTMASTER_DEATH;
@@ -1390,7 +1390,7 @@ WaitEventSetWaitBlock(WaitEventSet *set, int cur_timeout,
* even though there is no known reason to think that the event could
* be falsely set on Windows.
*/
- if (!PostmasterIsAlive())
+ if (!PostmasterIsAliveInternal())
{
occurred_events->fd = PGINVALID_SOCKET;
occurred_events->events = WL_POSTMASTER_DEATH;
diff --git a/src/backend/storage/ipc/pmsignal.c b/src/backend/storage/ipc/pmsignal.c
index be61858fc67..c415b8b5dbb 100644
--- a/src/backend/storage/ipc/pmsignal.c
+++ b/src/backend/storage/ipc/pmsignal.c
@@ -23,6 +23,9 @@
#include "storage/pmsignal.h"
#include "storage/shmem.h"
+#if defined(HAVE_PR_SET_PDEATHSIG)
+#include <sys/prctl.h>
+#endif
/*
* The postmaster is signaled by its children by sending SIGUSR1. The
@@ -71,6 +74,28 @@ struct PMSignalData
NON_EXEC_STATIC volatile PMSignalData *PMSignalState = NULL;
+#ifdef USE_POSTMASTER_DEATH_SIGNAL
+sig_atomic_t postmaster_possibly_dead = false;
+
+static void
+postmaster_death_handler(int signo)
+{
+ postmaster_possibly_dead = true;
+}
+
+/*
+ * The available signals depends on the OS and architecture. SIGUSR1 and
+ * SIGUSR2 are already used for other things, so choose another one.
+ */
+#if defined(SIGINFO)
+#define POSTMASTER_DEATH_SIGNAL SIGINFO
+#elif defined(SIGPWR)
+#define POSTMASTER_DEATH_SIGNAL SIGPWR
+#else
+#error "cannot find a signal to use for postmaster death"
+#endif
+
+#endif
/*
* PMSignalShmemSize
@@ -269,7 +294,7 @@ MarkPostmasterChildInactive(void)
* PostmasterIsAlive - check whether postmaster process is still alive
*/
bool
-PostmasterIsAlive(void)
+PostmasterIsAliveInternal(void)
{
#ifndef WIN32
char c;
@@ -291,3 +316,31 @@ PostmasterIsAlive(void)
return (WaitForSingleObject(PostmasterHandle, 0) == WAIT_TIMEOUT);
#endif /* WIN32 */
}
+
+/*
+ * PostmasterDeathInit - request signal on postmaster death if possible
+ */
+void
+PostmasterDeathInit(void)
+{
+#ifdef USE_POSTMASTER_DEATH_SIGNAL
+ int signum;
+
+ /* Register our signal handler. */
+ signum = POSTMASTER_DEATH_SIGNAL;
+ pqsignal(signum, postmaster_death_handler);
+
+ /* Request a signal on parent exit. */
+#ifdef HAVE_PR_SET_PDEATHSIG
+ if (prctl(PR_SET_PDEATHSIG, signum) < 0)
+ elog(ERROR, "could not request parent death signal: %m");
+#endif
+
+ /*
+ * Just in case the parent was gone already and we missed it, we'd
+ * better check the slow way.
+ */
+ if (!PostmasterIsAliveInternal())
+ postmaster_possibly_dead = true;
+#endif
+}
diff --git a/src/include/c.h b/src/include/c.h
index 95e9aeded9d..116c2a24814 100644
--- a/src/include/c.h
+++ b/src/include/c.h
@@ -1155,6 +1155,17 @@ extern int fdatasync(int fildes);
#define NON_EXEC_STATIC static
#endif
+/*
+ * Do we have a way to ask for a signal on parent death? Build with
+ * NO_POSTMASTER_DEATH_SIGNAL defined to inhibit the use of death signals on
+ * platforms that support it, for testing purposes.
+ */
+#ifndef NO_POSTMASTER_DEATH_SIGNAL
+#if defined(HAVE_PR_SET_PDEATHSIG)
+#define USE_POSTMASTER_DEATH_SIGNAL
+#endif
+#endif
+
/* /port compatibility functions */
#include "port.h"
diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in
index f3620231a71..5454f0d4807 100644
--- a/src/include/pg_config.h.in
+++ b/src/include/pg_config.h.in
@@ -428,6 +428,9 @@
/* Define to 1 if the assembler supports PPC's LWARX mutex hint bit. */
#undef HAVE_PPC_LWARX_MUTEX_HINT
+/* Define to 1 if the system supports PR_SET_PDEATHSIG */
+#undef HAVE_PR_SET_PDEATHSIG
+
/* Define to 1 if you have the `pstat' function. */
#undef HAVE_PSTAT
diff --git a/src/include/storage/pmsignal.h b/src/include/storage/pmsignal.h
index bec162cc16d..6667853bdc3 100644
--- a/src/include/storage/pmsignal.h
+++ b/src/include/storage/pmsignal.h
@@ -51,6 +51,21 @@ extern bool IsPostmasterChildWalSender(int slot);
extern void MarkPostmasterChildActive(void);
extern void MarkPostmasterChildInactive(void);
extern void MarkPostmasterChildWalSender(void);
-extern bool PostmasterIsAlive(void);
+extern bool PostmasterIsAliveInternal(void);
+extern void PostmasterDeathInit(void);
+
+#ifdef USE_POSTMASTER_DEATH_SIGNAL
+extern sig_atomic_t postmaster_possibly_dead;
+#endif
+
+static inline bool
+PostmasterIsAlive(void)
+{
+#ifdef USE_POSTMASTER_DEATH_SIGNAL
+ if (likely(!postmaster_possibly_dead))
+ return true;
+#endif
+ return PostmasterIsAliveInternal();
+}
#endif /* PMSIGNAL_H */
--
2.16.2