errdetail-pid-fix3.diff
application/octet-stream
Filename: errdetail-pid-fix3.diff
Type: application/octet-stream
Part: 0
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: unified
| File | + | − |
|---|---|---|
| src/backend/replication/syncrep.c | 12 | 16 |
| src/backend/tcop/postgres.c | 14 | 0 |
| src/include/libpq/pqsignal.h | 3 | 0 |
| src/port/pqsignal.c | 36 | 3 |
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