From 9ddd96f2da2332ef019c6da5825ae38cc820f2ac Mon Sep 17 00:00:00 2001 From: roman khapov 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 --- 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 + +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)