diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index 46a778f0917..73450fe437e 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -300,22 +300,18 @@ SyncRepWaitForLSN(XLogRecPtr lsn, bool commit) */ if (ProcDiePending) { - /* - * ProcDieSenderPid/Uid are read directly from the globals here - * rather than copied to locals first; a second SIGTERM could - * change them between reads, but that is harmless because the - * process is about to die anyway. The signal sender detail is - * inlined rather than using a separate errdetail() call because - * it must be appended to the existing detail message. - */ - ereport(WARNING, - (errcode(ERRCODE_ADMIN_SHUTDOWN), - errmsg("canceling the wait for synchronous replication and terminating connection due to administrator command"), - errdetail("The transaction has already committed locally, but might not have been replicated to the standby.%s", - ProcDieSenderPid == 0 ? "" : - psprintf("\nSignal sent by PID %d, UID %d.", - (int) ProcDieSenderPid, - (int) ProcDieSenderUid)))); + if (ProcDieSenderPid != 0) + ereport(WARNING, + (errcode(ERRCODE_ADMIN_SHUTDOWN), + errmsg("canceling the wait for synchronous replication and terminating connection due to administrator command"), + errdetail("The transaction has already committed locally, but might not have been replicated to the standby. Signal sent by PID %d, UID %d.", + (int) ProcDieSenderPid, + (int) ProcDieSenderUid))); + else + ereport(WARNING, + (errcode(ERRCODE_ADMIN_SHUTDOWN), + errmsg("canceling the wait for synchronous replication and terminating connection due to administrator command"), + errdetail("The transaction has already committed locally, but might not have been replicated to the standby."))); whereToSendOutput = DestNone; SyncRepCancelWait(); break; diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c index 14a061599bc..a9140492dcb 100644 --- a/src/backend/tcop/postgres.c +++ b/src/backend/tcop/postgres.c @@ -3024,6 +3024,20 @@ die(SIGNAL_ARGS) /* Don't joggle the elbow of proc_exit */ if (!proc_exit_inprogress) { + int sender_pid; + int sender_uid; + + if (pqsignal_get_sender(postgres_signal_arg, &sender_pid, &sender_uid)) + { + ProcDieSenderPid = sender_pid; + ProcDieSenderUid = sender_uid; + } + else + { + ProcDieSenderPid = 0; + ProcDieSenderUid = 0; + } + InterruptPending = true; ProcDiePending = true; } diff --git a/src/include/libpq/pqsignal.h b/src/include/libpq/pqsignal.h index 9f494a1fdf9..2ca32aee59e 100644 --- a/src/include/libpq/pqsignal.h +++ b/src/include/libpq/pqsignal.h @@ -50,5 +50,8 @@ extern PGDLLIMPORT sigset_t BlockSig; extern PGDLLIMPORT sigset_t StartupBlockSig; extern void pqinitmask(void); +#ifndef FRONTEND +extern bool pqsignal_get_sender(int signo, int *sender_pid, int *sender_uid); +#endif #endif /* PQSIGNAL_H */ diff --git a/src/port/pqsignal.c b/src/port/pqsignal.c index 8841464b5cb..8cb609e58d8 100644 --- a/src/port/pqsignal.c +++ b/src/port/pqsignal.c @@ -70,6 +70,11 @@ StaticAssertDecl(SIGTERM < PG_NSIG, "SIGTERM >= PG_NSIG"); StaticAssertDecl(SIGALRM < PG_NSIG, "SIGALRM >= PG_NSIG"); static volatile pqsigfunc pqsignal_handlers[PG_NSIG]; +#if !defined(FRONTEND) && defined(HAVE_SA_SIGINFO) +static volatile sig_atomic_t pqsignal_has_sender[PG_NSIG]; +static volatile sig_atomic_t pqsignal_sender_pid[PG_NSIG]; +static volatile sig_atomic_t pqsignal_sender_uid[PG_NSIG]; +#endif /* * Except when called with SIG_IGN or SIG_DFL, pqsignal() sets up this function @@ -116,16 +121,22 @@ wrapper_handler(SIGNAL_ARGS) } #ifdef HAVE_SA_SIGINFO - if (signo == SIGTERM && info) + if (info) { - ProcDieSenderPid = info->si_pid; - ProcDieSenderUid = info->si_uid; + pqsignal_has_sender[postgres_signal_arg] = 1; + pqsignal_sender_pid[postgres_signal_arg] = info->si_pid; + pqsignal_sender_uid[postgres_signal_arg] = info->si_uid; } + else + pqsignal_has_sender[postgres_signal_arg] = 0; #endif #endif (*pqsignal_handlers[postgres_signal_arg]) (postgres_signal_arg); +#if !defined(FRONTEND) && defined(HAVE_SA_SIGINFO) + pqsignal_has_sender[postgres_signal_arg] = 0; +#endif errno = save_errno; } @@ -180,3 +191,25 @@ pqsignal(int signo, pqsigfunc func) Assert(false); /* probably indicates coding error */ #endif } + +/* + * Return sender PID/UID for currently-dispatched signal if available. + */ +#ifndef FRONTEND +bool +pqsignal_get_sender(int signo, int *sender_pid, int *sender_uid) +{ +#ifdef HAVE_SA_SIGINFO + if (signo <= 0 || signo >= PG_NSIG || !pqsignal_has_sender[signo]) + return false; + + if (sender_pid) + *sender_pid = (int) pqsignal_sender_pid[signo]; + if (sender_uid) + *sender_uid = (int) pqsignal_sender_uid[signo]; + return true; +#else + return false; +#endif +} +#endif