0001-termination-msg-in-PGPROC.patch
application/octet-stream
Filename: 0001-termination-msg-in-PGPROC.patch
Type: application/octet-stream
Part: 0
From 9ddd96f2da2332ef019c6da5825ae38cc820f2ac Mon Sep 17 00:00:00 2001
From: roman khapov <r.khapov@ya.ru>
Date: Sat, 13 Dec 2025 06:55:28 +0000
Subject: [PATCH 1/2] termination msg in PGPROC
This commit adds message in PGPROC, that can be set
before terminating/cancelling connection, in order to add
this message when backend is responding to client with
'FATAL: terminating connection..' or 'ERROR: cancelling statement..'
For now there is no separated functions to perform termination with msg,
but that functions can be simply added in extension. This requires
implementation of pg_terminate_backend/pg_cancel_backend to be accessible
from extenions, so pg_terminate_backend_impl and pg_cancel_backend_impl was
introduced as public functions.
Signed-off-by: roman khapov <r.khapov@ya.ru>
---
src/backend/storage/ipc/signalfuncs.c | 32 +++++++++++++++++++--------
src/backend/tcop/postgres.c | 26 ++++++++++++++++++----
src/include/storage/proc.h | 6 +++++
src/include/storage/signalfuncs.h | 13 +++++++++++
4 files changed, 64 insertions(+), 13 deletions(-)
create mode 100644 src/include/storage/signalfuncs.h
diff --git a/src/backend/storage/ipc/signalfuncs.c b/src/backend/storage/ipc/signalfuncs.c
index a3a670ba24..cd7eeeb9e3 100644
--- a/src/backend/storage/ipc/signalfuncs.c
+++ b/src/backend/storage/ipc/signalfuncs.c
@@ -22,6 +22,7 @@
#include "postmaster/syslogger.h"
#include "storage/pmsignal.h"
#include "storage/proc.h"
+#include "storage/signalfuncs.h"
#include "storage/procarray.h"
#include "utils/acl.h"
#include "utils/fmgrprotos.h"
@@ -133,9 +134,9 @@ pg_signal_backend(int pid, int sig)
* Note that only superusers can signal superuser-owned processes.
*/
Datum
-pg_cancel_backend(PG_FUNCTION_ARGS)
+pg_cancel_backend_impl(int pid)
{
- int r = pg_signal_backend(PG_GETARG_INT32(0), SIGINT);
+ int r = pg_signal_backend(pid, SIGINT);
if (r == SIGNAL_BACKEND_NOSUPERUSER)
ereport(ERROR,
@@ -161,6 +162,12 @@ pg_cancel_backend(PG_FUNCTION_ARGS)
PG_RETURN_BOOL(r == SIGNAL_BACKEND_SUCCESS);
}
+Datum
+pg_cancel_backend(PG_FUNCTION_ARGS)
+{
+ return pg_cancel_backend_impl(PG_GETARG_INT32(0));
+}
+
/*
* Wait until there is no backend process with the given PID and return true.
* On timeout, a warning is emitted and false is returned.
@@ -234,14 +241,9 @@ pg_wait_until_termination(int pid, int64 timeout)
* Note that only superusers can signal superuser-owned processes.
*/
Datum
-pg_terminate_backend(PG_FUNCTION_ARGS)
+pg_terminate_backend_impl(int pid, int timeout)
{
- int pid;
- int r;
- int timeout; /* milliseconds */
-
- pid = PG_GETARG_INT32(0);
- timeout = PG_GETARG_INT64(1);
+ int r;
if (timeout < 0)
ereport(ERROR,
@@ -278,6 +280,18 @@ pg_terminate_backend(PG_FUNCTION_ARGS)
PG_RETURN_BOOL(r == SIGNAL_BACKEND_SUCCESS);
}
+Datum
+pg_terminate_backend(PG_FUNCTION_ARGS)
+{
+ int pid;
+ int timeout; /* milliseconds */
+
+ pid = PG_GETARG_INT32(0);
+ timeout = PG_GETARG_INT64(1);
+
+ return pg_terminate_backend_impl(pid, timeout);
+}
+
/*
* Signal to reload the database configuration
*
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 7dd75a490a..bb43d2db7e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3356,9 +3356,17 @@ ProcessInterrupts(void)
proc_exit(0);
}
else
- ereport(FATAL,
+ {
+ if (MyProc->termReasonStr[0] == '\0')
+ ereport(FATAL,
(errcode(ERRCODE_ADMIN_SHUTDOWN),
errmsg("terminating connection due to administrator command")));
+ else
+ ereport(FATAL,
+ (errcode(ERRCODE_ADMIN_SHUTDOWN),
+ errmsg("terminating connection due to administrator command: %s",
+ MyProc->termReasonStr)));
+ }
}
if (CheckClientConnectionPending)
@@ -3466,9 +3474,19 @@ ProcessInterrupts(void)
if (!DoingCommandRead)
{
LockErrorCleanup();
- ereport(ERROR,
- (errcode(ERRCODE_QUERY_CANCELED),
- errmsg("canceling statement due to user request")));
+ if (MyProc->termReasonStr[0] == '\0')
+ ereport(ERROR,
+ (errcode(ERRCODE_QUERY_CANCELED),
+ errmsg("canceling statement due to user request")));
+ else
+ {
+ ereport(ERROR,
+ (errcode(ERRCODE_QUERY_CANCELED),
+ errmsg("canceling statement due to user request: %s",
+ MyProc->termReasonStr)));
+
+ memset(MyProc->termReasonStr, 0, sizeof(MyProc->termReasonStr));
+ }
}
}
diff --git a/src/include/storage/proc.h b/src/include/storage/proc.h
index c6f5ebceef..f0f2bc4b93 100644
--- a/src/include/storage/proc.h
+++ b/src/include/storage/proc.h
@@ -77,6 +77,9 @@ struct XidCache
*/
#define PROC_XMIN_FLAGS (PROC_IN_VACUUM | PROC_IN_SAFE_IC)
+/* including the termination null byte */
+#define PROC_TERM_REASON_MAX_LEN 32
+
/*
* We allow a limited number of "weak" relation locks (AccessShareLock,
* RowShareLock, RowExclusiveLock) to be recorded in the PGPROC structure
@@ -301,6 +304,9 @@ struct PGPROC
uint32 wait_event_info; /* proc's wait information */
+ /* additional info when termination signal sending */
+ char termReasonStr[PROC_TERM_REASON_MAX_LEN];
+
/* Support for group transaction status update. */
bool clogGroupMember; /* true, if member of clog group */
pg_atomic_uint32 clogGroupNext; /* next clog group member */
diff --git a/src/include/storage/signalfuncs.h b/src/include/storage/signalfuncs.h
new file mode 100644
index 0000000000..359b3be67b
--- /dev/null
+++ b/src/include/storage/signalfuncs.h
@@ -0,0 +1,13 @@
+
+#ifndef SIGNALFUNCS_H
+#define SIGNALFUNCS_H
+
+#include <postgres.h>
+
+Datum
+pg_terminate_backend_impl(int pid, int timeout);
+
+Datum
+pg_cancel_backend_impl(int pid);
+
+#endif /* SIGNALFUNCS_H */
--
2.50.1 (Apple Git-155)