Skip to content

Commit 9f09529

Browse files
committed
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
1 parent 56a7147 commit 9f09529

File tree

8 files changed

+159
-19
lines changed

8 files changed

+159
-19
lines changed

configure

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12494,7 +12494,7 @@ $as_echo "#define HAVE_STDBOOL_H 1" >>confdefs.h
1249412494
fi
1249512495

1249612496

12497-
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
12497+
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
1249812498
do :
1249912499
as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
1250012500
ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"

configure.in

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1260,7 +1260,7 @@ AC_SUBST(UUID_LIBS)
12601260

12611261
AC_HEADER_STDBOOL
12621262

1263-
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])
1263+
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])
12641264

12651265
# On BSD, test for net/if.h will fail unless sys/socket.h
12661266
# is included first.

src/backend/storage/ipc/latch.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1112,7 +1112,7 @@ WaitEventSetWaitBlock(WaitEventSet *set, int cur_timeout,
11121112
* WL_POSTMASTER_DEATH event would be painful. Re-checking doesn't
11131113
* cost much.
11141114
*/
1115-
if (!PostmasterIsAlive())
1115+
if (!PostmasterIsAliveInternal())
11161116
{
11171117
occurred_events->fd = PGINVALID_SOCKET;
11181118
occurred_events->events = WL_POSTMASTER_DEATH;
@@ -1230,7 +1230,7 @@ WaitEventSetWaitBlock(WaitEventSet *set, int cur_timeout,
12301230
* WL_POSTMASTER_DEATH event would be painful. Re-checking doesn't
12311231
* cost much.
12321232
*/
1233-
if (!PostmasterIsAlive())
1233+
if (!PostmasterIsAliveInternal())
12341234
{
12351235
occurred_events->fd = PGINVALID_SOCKET;
12361236
occurred_events->events = WL_POSTMASTER_DEATH;
@@ -1390,7 +1390,7 @@ WaitEventSetWaitBlock(WaitEventSet *set, int cur_timeout,
13901390
* even though there is no known reason to think that the event could
13911391
* be falsely set on Windows.
13921392
*/
1393-
if (!PostmasterIsAlive())
1393+
if (!PostmasterIsAliveInternal())
13941394
{
13951395
occurred_events->fd = PGINVALID_SOCKET;
13961396
occurred_events->events = WL_POSTMASTER_DEATH;

src/backend/storage/ipc/pmsignal.c

Lines changed: 112 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@
1717
#include <signal.h>
1818
#include <unistd.h>
1919

20+
#ifdef HAVE_SYS_PRCTL_H
21+
#include <sys/prctl.h>
22+
#endif
23+
2024
#include "miscadmin.h"
2125
#include "postmaster/postmaster.h"
2226
#include "replication/walsender.h"
@@ -71,6 +75,35 @@ struct PMSignalData
7175

7276
NON_EXEC_STATIC volatile PMSignalData *PMSignalState = NULL;
7377

78+
/*
79+
* Signal handler to be notified if postmaster dies.
80+
*/
81+
#ifdef USE_POSTMASTER_DEATH_SIGNAL
82+
volatile sig_atomic_t postmaster_possibly_dead = false;
83+
84+
static void
85+
postmaster_death_handler(int signo)
86+
{
87+
postmaster_possibly_dead = true;
88+
}
89+
90+
/*
91+
* The available signals depend on the OS. SIGUSR1 and SIGUSR2 are already
92+
* used for other things, so choose another one.
93+
*
94+
* Currently, we assume that we can always find a signal to use. That
95+
* seems like a reasonable assumption for all platforms that are modern
96+
* enough to have a parent-death signaling mechanism.
97+
*/
98+
#if defined(SIGINFO)
99+
#define POSTMASTER_DEATH_SIGNAL SIGINFO
100+
#elif defined(SIGPWR)
101+
#define POSTMASTER_DEATH_SIGNAL SIGPWR
102+
#else
103+
#error "cannot find a signal to use for postmaster death"
104+
#endif
105+
106+
#endif /* USE_POSTMASTER_DEATH_SIGNAL */
74107

75108
/*
76109
* PMSignalShmemSize
@@ -266,28 +299,94 @@ MarkPostmasterChildInactive(void)
266299

267300

268301
/*
269-
* PostmasterIsAlive - check whether postmaster process is still alive
302+
* PostmasterIsAliveInternal - check whether postmaster process is still alive
303+
*
304+
* This is the slow path of PostmasterIsAlive(), where the caller has already
305+
* checked 'postmaster_possibly_dead'. (On platforms that don't support
306+
* a signal for parent death, PostmasterIsAlive() is just an alias for this.)
270307
*/
271308
bool
272-
PostmasterIsAlive(void)
309+
PostmasterIsAliveInternal(void)
273310
{
274-
#ifndef WIN32
275-
char c;
276-
ssize_t rc;
311+
#ifdef USE_POSTMASTER_DEATH_SIGNAL
312+
/*
313+
* Reset the flag before checking, so that we don't miss a signal if
314+
* postmaster dies right after the check. If postmaster was indeed dead,
315+
* we'll re-arm it before returning to caller.
316+
*/
317+
postmaster_possibly_dead = false;
318+
#endif
277319

278-
rc = read(postmaster_alive_fds[POSTMASTER_FD_WATCH], &c, 1);
279-
if (rc < 0)
320+
#ifndef WIN32
280321
{
281-
if (errno == EAGAIN || errno == EWOULDBLOCK)
322+
char c;
323+
ssize_t rc;
324+
325+
rc = read(postmaster_alive_fds[POSTMASTER_FD_WATCH], &c, 1);
326+
327+
/*
328+
* In the usual case, the postmaster is still alive, and there is no
329+
* data in the pipe.
330+
*/
331+
if (rc < 0 && (errno == EAGAIN || errno == EWOULDBLOCK))
282332
return true;
283333
else
284-
elog(FATAL, "read on postmaster death monitoring pipe failed: %m");
334+
{
335+
/*
336+
* Postmaster is dead, or something went wrong with the read()
337+
* call.
338+
*/
339+
340+
#ifdef USE_POSTMASTER_DEATH_SIGNAL
341+
postmaster_possibly_dead = true;
342+
#endif
343+
344+
if (rc < 0)
345+
elog(FATAL, "read on postmaster death monitoring pipe failed: %m");
346+
else if (rc > 0)
347+
elog(FATAL, "unexpected data in postmaster death monitoring pipe");
348+
349+
return false;
350+
}
285351
}
286-
else if (rc > 0)
287-
elog(FATAL, "unexpected data in postmaster death monitoring pipe");
288352

289-
return false;
290353
#else /* WIN32 */
291-
return (WaitForSingleObject(PostmasterHandle, 0) == WAIT_TIMEOUT);
354+
if (WaitForSingleObject(PostmasterHandle, 0) == WAIT_TIMEOUT)
355+
return true;
356+
else
357+
{
358+
#ifdef USE_POSTMASTER_DEATH_SIGNAL
359+
postmaster_possibly_dead = true;
360+
#endif
361+
return false;
362+
}
292363
#endif /* WIN32 */
293364
}
365+
366+
/*
367+
* PostmasterDeathSignalInit - request signal on postmaster death if possible
368+
*/
369+
void
370+
PostmasterDeathSignalInit(void)
371+
{
372+
#ifdef USE_POSTMASTER_DEATH_SIGNAL
373+
int signum = POSTMASTER_DEATH_SIGNAL;
374+
375+
/* Register our signal handler. */
376+
pqsignal(signum, postmaster_death_handler);
377+
378+
/* Request a signal on parent exit. */
379+
#if defined(PR_SET_PDEATHSIG)
380+
if (prctl(PR_SET_PDEATHSIG, signum) < 0)
381+
elog(ERROR, "could not request parent death signal: %m");
382+
#else
383+
#error "USE_POSTMASTER_DEATH_SIGNAL set, but there is no mechanism to request the signal"
384+
#endif
385+
386+
/*
387+
* Just in case the parent was gone already and we missed it, we'd better
388+
* check the slow way on the first call.
389+
*/
390+
postmaster_possibly_dead = true;
391+
#endif /* USE_POSTMASTER_DEATH_SIGNAL */
392+
}

src/backend/utils/init/miscinit.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
#include "storage/ipc.h"
4444
#include "storage/latch.h"
4545
#include "storage/pg_shmem.h"
46+
#include "storage/pmsignal.h"
4647
#include "storage/proc.h"
4748
#include "storage/procarray.h"
4849
#include "utils/builtins.h"
@@ -304,6 +305,9 @@ InitPostmasterChild(void)
304305
if (setsid() < 0)
305306
elog(FATAL, "setsid() failed: %m");
306307
#endif
308+
309+
/* Request a signal if the postmaster dies, if possible. */
310+
PostmasterDeathSignalInit();
307311
}
308312

309313
/*

src/include/pg_config.h.in

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -600,6 +600,9 @@
600600
/* Define to 1 if you have the <sys/ipc.h> header file. */
601601
#undef HAVE_SYS_IPC_H
602602

603+
/* Define to 1 if you have the <sys/prctl.h> header file. */
604+
#undef HAVE_SYS_PRCTL_H
605+
603606
/* Define to 1 if you have the <sys/pstat.h> header file. */
604607
#undef HAVE_SYS_PSTAT_H
605608

src/include/pg_config.h.win32

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -482,6 +482,9 @@
482482
/* Define to 1 if you have the <sys/ipc.h> header file. */
483483
/* #undef HAVE_SYS_IPC_H */
484484

485+
/* Define to 1 if you have the <sys/prctl.h> header file. */
486+
/* #undef HAVE_SYS_PRCTL_H */
487+
485488
/* Define to 1 if you have the <sys/pstat.h> header file. */
486489
/* #undef HAVE_SYS_PSTAT_H */
487490

src/include/storage/pmsignal.h

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@
1414
#ifndef PMSIGNAL_H
1515
#define PMSIGNAL_H
1616

17+
#ifdef HAVE_SYS_PRCTL_H
18+
#include "sys/prctl.h"
19+
#endif
20+
1721
/*
1822
* Reasons for signaling the postmaster. We can cope with simultaneous
1923
* signals for different reasons. If the same reason is signaled multiple
@@ -51,6 +55,33 @@ extern bool IsPostmasterChildWalSender(int slot);
5155
extern void MarkPostmasterChildActive(void);
5256
extern void MarkPostmasterChildInactive(void);
5357
extern void MarkPostmasterChildWalSender(void);
54-
extern bool PostmasterIsAlive(void);
58+
extern bool PostmasterIsAliveInternal(void);
59+
extern void PostmasterDeathSignalInit(void);
60+
61+
62+
/*
63+
* Do we have a way to ask for a signal on parent death?
64+
*
65+
* If we do, pmsignal.c will set up a signal handler, that sets a flag when
66+
* the parent dies. Checking the flag first makes PostmasterIsAlive() a lot
67+
* cheaper in usual case that the postmaster is alive.
68+
*/
69+
#if defined(HAVE_SYS_PRCTL_H) && defined(PR_SET_PDEATHSIG)
70+
#define USE_POSTMASTER_DEATH_SIGNAL
71+
#endif
72+
73+
#ifdef USE_POSTMASTER_DEATH_SIGNAL
74+
extern volatile sig_atomic_t postmaster_possibly_dead;
75+
76+
static inline bool
77+
PostmasterIsAlive(void)
78+
{
79+
if (likely(!postmaster_possibly_dead))
80+
return true;
81+
return PostmasterIsAliveInternal();
82+
}
83+
#else
84+
#define PostmasterIsAlive() PostmasterIsAliveInternal()
85+
#endif
5586

5687
#endif /* PMSIGNAL_H */

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy