|
17 | 17 | #include <signal.h>
|
18 | 18 | #include <unistd.h>
|
19 | 19 |
|
| 20 | +#ifdef HAVE_SYS_PRCTL_H |
| 21 | +#include <sys/prctl.h> |
| 22 | +#endif |
| 23 | + |
20 | 24 | #include "miscadmin.h"
|
21 | 25 | #include "postmaster/postmaster.h"
|
22 | 26 | #include "replication/walsender.h"
|
@@ -71,6 +75,35 @@ struct PMSignalData
|
71 | 75 |
|
72 | 76 | NON_EXEC_STATIC volatile PMSignalData *PMSignalState = NULL;
|
73 | 77 |
|
| 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 */ |
74 | 107 |
|
75 | 108 | /*
|
76 | 109 | * PMSignalShmemSize
|
@@ -266,28 +299,94 @@ MarkPostmasterChildInactive(void)
|
266 | 299 |
|
267 | 300 |
|
268 | 301 | /*
|
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.) |
270 | 307 | */
|
271 | 308 | bool
|
272 |
| -PostmasterIsAlive(void) |
| 309 | +PostmasterIsAliveInternal(void) |
273 | 310 | {
|
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 |
277 | 319 |
|
278 |
| - rc = read(postmaster_alive_fds[POSTMASTER_FD_WATCH], &c, 1); |
279 |
| - if (rc < 0) |
| 320 | +#ifndef WIN32 |
280 | 321 | {
|
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)) |
282 | 332 | return true;
|
283 | 333 | 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 | + } |
285 | 351 | }
|
286 |
| - else if (rc > 0) |
287 |
| - elog(FATAL, "unexpected data in postmaster death monitoring pipe"); |
288 | 352 |
|
289 |
| - return false; |
290 | 353 | #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 | + } |
292 | 363 | #endif /* WIN32 */
|
293 | 364 | }
|
| 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 | +} |
0 commit comments