mirror of
https://github.com/postgres/postgres.git
synced 2025-05-21 00:02:53 -04:00
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. Based on a suggestion from Andres Freund. Author: Thomas Munro, Heikki Linnakangas Reviewed-By: Michael Paquier Discussion: https://postgr.es/m/7261eb39-0369-f2f4-1bb5-62f3b6083b5e%40iki.fi Discussion: https://postgr.es/m/20180411002643.6buofht4ranhei7k%40alap3.anarazel.de
This commit is contained in:
parent
56a7147213
commit
9f09529952
2
configure
vendored
2
configure
vendored
@ -12494,7 +12494,7 @@ $as_echo "#define HAVE_STDBOOL_H 1" >>confdefs.h
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
for ac_header in atomic.h crypt.h dld.h fp_class.h getopt.h ieeefp.h ifaddrs.h langinfo.h mbarrier.h poll.h sys/epoll.h sys/ipc.h sys/pstat.h sys/resource.h sys/select.h sys/sem.h sys/shm.h sys/sockio.h sys/tas.h sys/un.h termios.h ucred.h utime.h wchar.h wctype.h
|
for ac_header in atomic.h crypt.h dld.h fp_class.h getopt.h ieeefp.h ifaddrs.h langinfo.h mbarrier.h poll.h sys/epoll.h sys/ipc.h sys/prctl.h sys/pstat.h sys/resource.h sys/select.h sys/sem.h sys/shm.h sys/sockio.h sys/tas.h sys/un.h termios.h ucred.h utime.h wchar.h wctype.h
|
||||||
do :
|
do :
|
||||||
as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
|
as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
|
||||||
ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
|
ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
|
||||||
|
@ -1260,7 +1260,7 @@ AC_SUBST(UUID_LIBS)
|
|||||||
|
|
||||||
AC_HEADER_STDBOOL
|
AC_HEADER_STDBOOL
|
||||||
|
|
||||||
AC_CHECK_HEADERS([atomic.h crypt.h dld.h fp_class.h getopt.h ieeefp.h ifaddrs.h langinfo.h mbarrier.h poll.h sys/epoll.h sys/ipc.h sys/pstat.h sys/resource.h sys/select.h sys/sem.h sys/shm.h sys/sockio.h sys/tas.h sys/un.h termios.h ucred.h utime.h wchar.h wctype.h])
|
AC_CHECK_HEADERS([atomic.h crypt.h dld.h fp_class.h getopt.h ieeefp.h ifaddrs.h langinfo.h mbarrier.h poll.h sys/epoll.h sys/ipc.h sys/prctl.h sys/pstat.h sys/resource.h sys/select.h sys/sem.h sys/shm.h sys/sockio.h sys/tas.h sys/un.h termios.h ucred.h utime.h wchar.h wctype.h])
|
||||||
|
|
||||||
# On BSD, test for net/if.h will fail unless sys/socket.h
|
# On BSD, test for net/if.h will fail unless sys/socket.h
|
||||||
# is included first.
|
# is included first.
|
||||||
|
@ -1112,7 +1112,7 @@ WaitEventSetWaitBlock(WaitEventSet *set, int cur_timeout,
|
|||||||
* WL_POSTMASTER_DEATH event would be painful. Re-checking doesn't
|
* WL_POSTMASTER_DEATH event would be painful. Re-checking doesn't
|
||||||
* cost much.
|
* cost much.
|
||||||
*/
|
*/
|
||||||
if (!PostmasterIsAlive())
|
if (!PostmasterIsAliveInternal())
|
||||||
{
|
{
|
||||||
occurred_events->fd = PGINVALID_SOCKET;
|
occurred_events->fd = PGINVALID_SOCKET;
|
||||||
occurred_events->events = WL_POSTMASTER_DEATH;
|
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
|
* WL_POSTMASTER_DEATH event would be painful. Re-checking doesn't
|
||||||
* cost much.
|
* cost much.
|
||||||
*/
|
*/
|
||||||
if (!PostmasterIsAlive())
|
if (!PostmasterIsAliveInternal())
|
||||||
{
|
{
|
||||||
occurred_events->fd = PGINVALID_SOCKET;
|
occurred_events->fd = PGINVALID_SOCKET;
|
||||||
occurred_events->events = WL_POSTMASTER_DEATH;
|
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
|
* even though there is no known reason to think that the event could
|
||||||
* be falsely set on Windows.
|
* be falsely set on Windows.
|
||||||
*/
|
*/
|
||||||
if (!PostmasterIsAlive())
|
if (!PostmasterIsAliveInternal())
|
||||||
{
|
{
|
||||||
occurred_events->fd = PGINVALID_SOCKET;
|
occurred_events->fd = PGINVALID_SOCKET;
|
||||||
occurred_events->events = WL_POSTMASTER_DEATH;
|
occurred_events->events = WL_POSTMASTER_DEATH;
|
||||||
|
@ -17,6 +17,10 @@
|
|||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_SYS_PRCTL_H
|
||||||
|
#include <sys/prctl.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "miscadmin.h"
|
#include "miscadmin.h"
|
||||||
#include "postmaster/postmaster.h"
|
#include "postmaster/postmaster.h"
|
||||||
#include "replication/walsender.h"
|
#include "replication/walsender.h"
|
||||||
@ -71,6 +75,35 @@ struct PMSignalData
|
|||||||
|
|
||||||
NON_EXEC_STATIC volatile PMSignalData *PMSignalState = NULL;
|
NON_EXEC_STATIC volatile PMSignalData *PMSignalState = NULL;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Signal handler to be notified if postmaster dies.
|
||||||
|
*/
|
||||||
|
#ifdef USE_POSTMASTER_DEATH_SIGNAL
|
||||||
|
volatile sig_atomic_t postmaster_possibly_dead = false;
|
||||||
|
|
||||||
|
static void
|
||||||
|
postmaster_death_handler(int signo)
|
||||||
|
{
|
||||||
|
postmaster_possibly_dead = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The available signals depend on the OS. SIGUSR1 and SIGUSR2 are already
|
||||||
|
* used for other things, so choose another one.
|
||||||
|
*
|
||||||
|
* Currently, we assume that we can always find a signal to use. That
|
||||||
|
* seems like a reasonable assumption for all platforms that are modern
|
||||||
|
* enough to have a parent-death signaling mechanism.
|
||||||
|
*/
|
||||||
|
#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 /* USE_POSTMASTER_DEATH_SIGNAL */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* PMSignalShmemSize
|
* PMSignalShmemSize
|
||||||
@ -266,28 +299,94 @@ MarkPostmasterChildInactive(void)
|
|||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* PostmasterIsAlive - check whether postmaster process is still alive
|
* PostmasterIsAliveInternal - check whether postmaster process is still alive
|
||||||
|
*
|
||||||
|
* This is the slow path of PostmasterIsAlive(), where the caller has already
|
||||||
|
* checked 'postmaster_possibly_dead'. (On platforms that don't support
|
||||||
|
* a signal for parent death, PostmasterIsAlive() is just an alias for this.)
|
||||||
*/
|
*/
|
||||||
bool
|
bool
|
||||||
PostmasterIsAlive(void)
|
PostmasterIsAliveInternal(void)
|
||||||
{
|
{
|
||||||
#ifndef WIN32
|
#ifdef USE_POSTMASTER_DEATH_SIGNAL
|
||||||
char c;
|
/*
|
||||||
ssize_t rc;
|
* Reset the flag before checking, so that we don't miss a signal if
|
||||||
|
* postmaster dies right after the check. If postmaster was indeed dead,
|
||||||
|
* we'll re-arm it before returning to caller.
|
||||||
|
*/
|
||||||
|
postmaster_possibly_dead = false;
|
||||||
|
#endif
|
||||||
|
|
||||||
rc = read(postmaster_alive_fds[POSTMASTER_FD_WATCH], &c, 1);
|
#ifndef WIN32
|
||||||
if (rc < 0)
|
|
||||||
{
|
{
|
||||||
if (errno == EAGAIN || errno == EWOULDBLOCK)
|
char c;
|
||||||
|
ssize_t rc;
|
||||||
|
|
||||||
|
rc = read(postmaster_alive_fds[POSTMASTER_FD_WATCH], &c, 1);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* In the usual case, the postmaster is still alive, and there is no
|
||||||
|
* data in the pipe.
|
||||||
|
*/
|
||||||
|
if (rc < 0 && (errno == EAGAIN || errno == EWOULDBLOCK))
|
||||||
return true;
|
return true;
|
||||||
else
|
else
|
||||||
elog(FATAL, "read on postmaster death monitoring pipe failed: %m");
|
{
|
||||||
}
|
/*
|
||||||
else if (rc > 0)
|
* Postmaster is dead, or something went wrong with the read()
|
||||||
elog(FATAL, "unexpected data in postmaster death monitoring pipe");
|
* call.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef USE_POSTMASTER_DEATH_SIGNAL
|
||||||
|
postmaster_possibly_dead = true;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (rc < 0)
|
||||||
|
elog(FATAL, "read on postmaster death monitoring pipe failed: %m");
|
||||||
|
else if (rc > 0)
|
||||||
|
elog(FATAL, "unexpected data in postmaster death monitoring pipe");
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
|
||||||
#else /* WIN32 */
|
#else /* WIN32 */
|
||||||
return (WaitForSingleObject(PostmasterHandle, 0) == WAIT_TIMEOUT);
|
if (WaitForSingleObject(PostmasterHandle, 0) == WAIT_TIMEOUT)
|
||||||
|
return true;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#ifdef USE_POSTMASTER_DEATH_SIGNAL
|
||||||
|
postmaster_possibly_dead = true;
|
||||||
|
#endif
|
||||||
|
return false;
|
||||||
|
}
|
||||||
#endif /* WIN32 */
|
#endif /* WIN32 */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* PostmasterDeathSignalInit - request signal on postmaster death if possible
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
PostmasterDeathSignalInit(void)
|
||||||
|
{
|
||||||
|
#ifdef USE_POSTMASTER_DEATH_SIGNAL
|
||||||
|
int signum = POSTMASTER_DEATH_SIGNAL;
|
||||||
|
|
||||||
|
/* Register our signal handler. */
|
||||||
|
pqsignal(signum, postmaster_death_handler);
|
||||||
|
|
||||||
|
/* Request a signal on parent exit. */
|
||||||
|
#if defined(PR_SET_PDEATHSIG)
|
||||||
|
if (prctl(PR_SET_PDEATHSIG, signum) < 0)
|
||||||
|
elog(ERROR, "could not request parent death signal: %m");
|
||||||
|
#else
|
||||||
|
#error "USE_POSTMASTER_DEATH_SIGNAL set, but there is no mechanism to request the signal"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Just in case the parent was gone already and we missed it, we'd better
|
||||||
|
* check the slow way on the first call.
|
||||||
|
*/
|
||||||
|
postmaster_possibly_dead = true;
|
||||||
|
#endif /* USE_POSTMASTER_DEATH_SIGNAL */
|
||||||
|
}
|
||||||
|
@ -43,6 +43,7 @@
|
|||||||
#include "storage/ipc.h"
|
#include "storage/ipc.h"
|
||||||
#include "storage/latch.h"
|
#include "storage/latch.h"
|
||||||
#include "storage/pg_shmem.h"
|
#include "storage/pg_shmem.h"
|
||||||
|
#include "storage/pmsignal.h"
|
||||||
#include "storage/proc.h"
|
#include "storage/proc.h"
|
||||||
#include "storage/procarray.h"
|
#include "storage/procarray.h"
|
||||||
#include "utils/builtins.h"
|
#include "utils/builtins.h"
|
||||||
@ -304,6 +305,9 @@ InitPostmasterChild(void)
|
|||||||
if (setsid() < 0)
|
if (setsid() < 0)
|
||||||
elog(FATAL, "setsid() failed: %m");
|
elog(FATAL, "setsid() failed: %m");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Request a signal if the postmaster dies, if possible. */
|
||||||
|
PostmasterDeathSignalInit();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -600,6 +600,9 @@
|
|||||||
/* Define to 1 if you have the <sys/ipc.h> header file. */
|
/* Define to 1 if you have the <sys/ipc.h> header file. */
|
||||||
#undef HAVE_SYS_IPC_H
|
#undef HAVE_SYS_IPC_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <sys/prctl.h> header file. */
|
||||||
|
#undef HAVE_SYS_PRCTL_H
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/pstat.h> header file. */
|
/* Define to 1 if you have the <sys/pstat.h> header file. */
|
||||||
#undef HAVE_SYS_PSTAT_H
|
#undef HAVE_SYS_PSTAT_H
|
||||||
|
|
||||||
|
@ -482,6 +482,9 @@
|
|||||||
/* Define to 1 if you have the <sys/ipc.h> header file. */
|
/* Define to 1 if you have the <sys/ipc.h> header file. */
|
||||||
/* #undef HAVE_SYS_IPC_H */
|
/* #undef HAVE_SYS_IPC_H */
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <sys/prctl.h> header file. */
|
||||||
|
/* #undef HAVE_SYS_PRCTL_H */
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/pstat.h> header file. */
|
/* Define to 1 if you have the <sys/pstat.h> header file. */
|
||||||
/* #undef HAVE_SYS_PSTAT_H */
|
/* #undef HAVE_SYS_PSTAT_H */
|
||||||
|
|
||||||
|
@ -14,6 +14,10 @@
|
|||||||
#ifndef PMSIGNAL_H
|
#ifndef PMSIGNAL_H
|
||||||
#define PMSIGNAL_H
|
#define PMSIGNAL_H
|
||||||
|
|
||||||
|
#ifdef HAVE_SYS_PRCTL_H
|
||||||
|
#include "sys/prctl.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Reasons for signaling the postmaster. We can cope with simultaneous
|
* Reasons for signaling the postmaster. We can cope with simultaneous
|
||||||
* signals for different reasons. If the same reason is signaled multiple
|
* signals for different reasons. If the same reason is signaled multiple
|
||||||
@ -51,6 +55,33 @@ extern bool IsPostmasterChildWalSender(int slot);
|
|||||||
extern void MarkPostmasterChildActive(void);
|
extern void MarkPostmasterChildActive(void);
|
||||||
extern void MarkPostmasterChildInactive(void);
|
extern void MarkPostmasterChildInactive(void);
|
||||||
extern void MarkPostmasterChildWalSender(void);
|
extern void MarkPostmasterChildWalSender(void);
|
||||||
extern bool PostmasterIsAlive(void);
|
extern bool PostmasterIsAliveInternal(void);
|
||||||
|
extern void PostmasterDeathSignalInit(void);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Do we have a way to ask for a signal on parent death?
|
||||||
|
*
|
||||||
|
* If we do, pmsignal.c will set up a signal handler, that sets a flag when
|
||||||
|
* the parent dies. Checking the flag first makes PostmasterIsAlive() a lot
|
||||||
|
* cheaper in usual case that the postmaster is alive.
|
||||||
|
*/
|
||||||
|
#if defined(HAVE_SYS_PRCTL_H) && defined(PR_SET_PDEATHSIG)
|
||||||
|
#define USE_POSTMASTER_DEATH_SIGNAL
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_POSTMASTER_DEATH_SIGNAL
|
||||||
|
extern volatile sig_atomic_t postmaster_possibly_dead;
|
||||||
|
|
||||||
|
static inline bool
|
||||||
|
PostmasterIsAlive(void)
|
||||||
|
{
|
||||||
|
if (likely(!postmaster_possibly_dead))
|
||||||
|
return true;
|
||||||
|
return PostmasterIsAliveInternal();
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#define PostmasterIsAlive() PostmasterIsAliveInternal()
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* PMSIGNAL_H */
|
#endif /* PMSIGNAL_H */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user