v28-0002-Extend-backtrace-logging-function-to-auxiliary-p.patch
application/octet-stream
Filename: v28-0002-Extend-backtrace-logging-function-to-auxiliary-p.patch
Type: application/octet-stream
Part: 0
Patch
Format: format-patch
Series: patch v28-0002
Subject: Extend backtrace logging function to auxiliary processes
| File | + | − |
|---|---|---|
| doc/src/sgml/func.sgml | 7 | 5 |
| src/backend/storage/ipc/procbacktrace.c | 25 | 10 |
| src/test/regress/expected/misc_functions.out | 8 | 0 |
| src/test/regress/sql/misc_functions.sql | 3 | 0 |
From 3cf748bb3dd891ae0a478698cfcef93b95a3eed0 Mon Sep 17 00:00:00 2001
From: Bharath Rupireddy <bharath.rupireddyforpostgres@gmail.com>
Date: Wed, 7 Feb 2024 14:39:14 +0000
Subject: [PATCH v28 2/2] Extend backtrace logging function to auxiliary
processes
---
doc/src/sgml/func.sgml | 12 ++++---
src/backend/storage/ipc/procbacktrace.c | 35 ++++++++++++++------
src/test/regress/expected/misc_functions.out | 8 +++++
src/test/regress/sql/misc_functions.sql | 3 ++
4 files changed, 43 insertions(+), 15 deletions(-)
diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml
index b7d7305331..b810a3dcaf 100644
--- a/doc/src/sgml/func.sgml
+++ b/doc/src/sgml/func.sgml
@@ -27196,11 +27196,13 @@ SELECT collation for ('foo' COLLATE "de_DE");
</para>
<para>
Requests to log the backtrace of a backend with the specified process
- ID. The backtraces will be logged to <systemitem>stderr</systemitem>.
- Typically, a backtrace identifies which function a process is currently
- executing, and is useful for developers to diagnose stuck processes.
- This function is supported only if PostgreSQL was built with the
- ability to capture backtraces, otherwise it will emit a warning.
+ ID. This function can send the request to backends and auxiliary
+ processes except logger. The backtraces will be logged to
+ <systemitem>stderr</systemitem>. Typically, a backtrace identifies
+ which function a process is currently executing, and is useful for
+ developers to diagnose stuck processes. This function is supported only
+ if PostgreSQL was built with the ability to capture backtraces,
+ otherwise it will emit a warning.
</para></entry>
</row>
diff --git a/src/backend/storage/ipc/procbacktrace.c b/src/backend/storage/ipc/procbacktrace.c
index bfab5783da..b85684cd19 100644
--- a/src/backend/storage/ipc/procbacktrace.c
+++ b/src/backend/storage/ipc/procbacktrace.c
@@ -92,15 +92,15 @@ LoadBacktraceFunctions(void)
/*
* pg_log_backend_backtrace
- * Signal a backend to log its current backtrace.
+ * Signal a backend or an auxiliary process to log its current backtrace.
*
* By default, only superusers are allowed to signal to log the backtrace
* because allowing any users to issue this request at an unbounded
* rate would cause lots of log messages on stderr and which can lead to
* denial of service. Additional roles can be permitted with GRANT.
*
- * On receipt of this signal, a backend emits the current backtrace to stderr
- * in the signal handler.
+ * On receipt of this signal, a backend or an auxiliary process emits the
+ * current backtrace to stderr in the signal handler.
*/
Datum
pg_log_backend_backtrace(PG_FUNCTION_ARGS)
@@ -108,15 +108,31 @@ pg_log_backend_backtrace(PG_FUNCTION_ARGS)
#ifdef HAVE_BACKTRACE_SYMBOLS
int pid = PG_GETARG_INT32(0);
PGPROC *proc;
+ BackendId backendId = InvalidBackendId;
proc = BackendPidGetProc(pid);
/*
- * BackendPidGetProc returns NULL if the pid isn't valid.
+ * See if the process with given pid is a backend or an auxiliary process.
*
- * Note that the proc will also be NULL if the pid refers to an auxiliary
- * process or the postmaster (neither of which can be signaled via
- * pg_log_backend_backtrace() to get backtrace).
+ * If the given process is a backend, use its backend id in
+ * SendProcSignal() later to speed up the operation. Otherwise, don't do
+ * that because auxiliary processes (except the startup process) don't
+ * have a valid backend id.
+ */
+ if (proc != NULL)
+ backendId = proc->backendId;
+ else
+ proc = AuxiliaryPidGetProc(pid);
+
+ /*
+ * BackendPidGetProc() and AuxiliaryPidGetProc() return NULL if the pid
+ * isn't valid; but by the time we reach kill(), a process for which we
+ * get a valid proc here might have terminated on its own. There's no way
+ * to acquire a lock on an arbitrary process to prevent that. But since
+ * this mechanism is usually used to debug a backend or an auxiliary
+ * process running and consuming lots of memory, that it might end on its
+ * own first and its memory contexts are not logged is not a problem.
*/
if (proc == NULL)
{
@@ -125,12 +141,11 @@ pg_log_backend_backtrace(PG_FUNCTION_ARGS)
* if one backend terminated on its own during the run.
*/
ereport(WARNING,
- (errmsg("PID %d is not a PostgreSQL backend process", pid)));
-
+ (errmsg("PID %d is not a PostgreSQL server process", pid)));
PG_RETURN_BOOL(false);
}
- if (SendProcSignal(pid, PROCSIG_LOG_BACKTRACE, proc->backendId) < 0)
+ if (SendProcSignal(pid, PROCSIG_LOG_BACKTRACE, backendId) < 0)
{
/* Again, just a warning to allow loops */
ereport(WARNING,
diff --git a/src/test/regress/expected/misc_functions.out b/src/test/regress/expected/misc_functions.out
index 3ff0136347..8751538c57 100644
--- a/src/test/regress/expected/misc_functions.out
+++ b/src/test/regress/expected/misc_functions.out
@@ -341,6 +341,14 @@ SELECT count(*) > 0 AS ok FROM pg_log_backend_backtrace(pg_backend_pid());
t
(1 row)
+SELECT pid AS c_pid FROM pg_stat_activity
+ WHERE backend_type = 'checkpointer' \gset
+SELECT count(*) > 0 AS ok FROM pg_log_backend_backtrace(:c_pid);
+ ok
+----
+ t
+(1 row)
+
RESET client_min_messages;
CREATE ROLE regress_log_backtrace;
SELECT has_function_privilege('regress_log_backtrace',
diff --git a/src/test/regress/sql/misc_functions.sql b/src/test/regress/sql/misc_functions.sql
index 2a3f9bacaa..0e51974ac3 100644
--- a/src/test/regress/sql/misc_functions.sql
+++ b/src/test/regress/sql/misc_functions.sql
@@ -114,6 +114,9 @@ DROP ROLE regress_log_memory;
-- generation support.
SET client_min_messages = 'ERROR';
SELECT count(*) > 0 AS ok FROM pg_log_backend_backtrace(pg_backend_pid());
+SELECT pid AS c_pid FROM pg_stat_activity
+ WHERE backend_type = 'checkpointer' \gset
+SELECT count(*) > 0 AS ok FROM pg_log_backend_backtrace(:c_pid);
RESET client_min_messages;
CREATE ROLE regress_log_backtrace;
--
2.34.1