v14-0002-pg_log_backtrace-support-for-logging-backtrace-o.patch
text/x-patch
Filename: v14-0002-pg_log_backtrace-support-for-logging-backtrace-o.patch
Type: text/x-patch
Part: 1
Patch
Format: format-patch
Series: patch v14-0002
Subject: pg_log_backtrace support for logging backtrace of aux procs
| File | + | − |
|---|---|---|
| doc/src/sgml/func.sgml | 16 | 10 |
| src/backend/postmaster/checkpointer.c | 4 | 0 |
| src/backend/postmaster/interrupt.c | 4 | 0 |
| src/backend/postmaster/pgarch.c | 4 | 0 |
| src/backend/postmaster/startup.c | 4 | 0 |
| src/backend/postmaster/walwriter.c | 4 | 0 |
| src/backend/storage/ipc/procsignal.c | 1 | 2 |
| src/backend/storage/ipc/signalfuncs.c | 25 | 10 |
| src/test/regress/expected/backtrace_1.out | 13 | 0 |
| src/test/regress/expected/backtrace.out | 11 | 0 |
| src/test/regress/sql/backtrace.sql | 9 | 0 |
From fea4198a289d20d4ec1cb0523d8ef91c5d298ce7 Mon Sep 17 00:00:00 2001
From: Vignesh C <vignesh21@gmail.com>
Date: Wed, 17 Nov 2021 08:40:18 +0530
Subject: [PATCH v14 2/2] pg_log_backtrace support for logging backtrace of aux
procs
Enhanced pg_log_backtrace to support logging backtrace of auxiliary
processes such as bgwriter, checkpointer, wal writer, archiver, startup
process and wal receiver. It will be useful to look at the backtrace of
these processes too, for debugging purposes and to check if the process
is genuinely taking time or if it is a stuck process. Inside the code,
we could use the AuxiliaryPidGetProc() to get the PGPROC of these
processes. Note that, neither AuxiliaryPidGetProc() nor
---
doc/src/sgml/func.sgml | 26 ++++++++++-------
src/backend/postmaster/checkpointer.c | 4 +++
src/backend/postmaster/interrupt.c | 4 +++
src/backend/postmaster/pgarch.c | 4 +++
src/backend/postmaster/startup.c | 4 +++
src/backend/postmaster/walwriter.c | 4 +++
src/backend/storage/ipc/procsignal.c | 3 +-
src/backend/storage/ipc/signalfuncs.c | 35 ++++++++++++++++-------
src/test/regress/expected/backtrace.out | 11 +++++++
src/test/regress/expected/backtrace_1.out | 13 +++++++++
src/test/regress/sql/backtrace.sql | 9 ++++++
11 files changed, 95 insertions(+), 22 deletions(-)
diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml
index a88583edfd..7e245711da 100644
--- a/doc/src/sgml/func.sgml
+++ b/doc/src/sgml/func.sgml
@@ -25355,19 +25355,25 @@ SELECT collation for ('foo' COLLATE "de_DE");
</para>
<para>
Requests to log the backtrace of the
- <glossterm linkend="glossary-backend">backend</glossterm>
- with the specified process ID. The backtrace will be logged at message
- level <literal>LOG</literal>. It will appear in the server log based on
- the log configuration set (See <xref linkend="runtime-config-logging"/>
- for more information), but will not be sent to the client regardless of
+ <glossterm linkend="glossary-backend">backend</glossterm> or the
+ <glossterm linkend="glossary-wal-sender">WAL sender</glossterm> or the
+ <glossterm linkend="glossary-auxiliary-proc">auxiliary process</glossterm>
+ with the specified process ID. This function cannot request
+ <glossterm linkend="glossary-postmaster">postmaster process</glossterm> or
+ <glossterm linkend="glossary-logger">logger</glossterm> or
+ <glossterm linkend="glossary-stats-collector">statistics collector</glossterm>
+ (all other <glossterm linkend="glossary-auxiliary-proc">auxiliary processes</glossterm>
+ it can) for the backtrace. The backtrace will be logged at
+ <literal>LOG</literal> message level. They will appear in the server
+ log based on the log configuration set (See
+ <xref linkend="runtime-config-logging"/> for more information), but
+ will not be sent to the client regardless of
<xref linkend="guc-client-min-messages"/>. A backtrace will identify
where exactly the backend process is currently executing. This may be
useful to developers to diagnose stuck processes and other problems.
- This feature is not supported for the postmaster, logger, checkpointer,
- walwriter, background writer or statistics collector process. This
- feature will be available if PostgreSQL was built with the ability to
- capture backtrace. If not available, the function will emit a warning
- and return false.
+ This feature will be available if PostgreSQL was built with the
+ ability to capture backtrace. If not available, the function will emit
+ a warning and return false.
</para></entry>
</row>
diff --git a/src/backend/postmaster/checkpointer.c b/src/backend/postmaster/checkpointer.c
index be7366379d..7a25557702 100644
--- a/src/backend/postmaster/checkpointer.c
+++ b/src/backend/postmaster/checkpointer.c
@@ -581,6 +581,10 @@ HandleCheckpointerInterrupts(void)
/* Normal exit from the checkpointer is here */
proc_exit(0); /* done */
}
+
+ /* Process logging backtrace */
+ if (LogBacktracePending)
+ ProcessLogBacktraceInterrupt();
}
/*
diff --git a/src/backend/postmaster/interrupt.c b/src/backend/postmaster/interrupt.c
index dd9136a942..6298b48da3 100644
--- a/src/backend/postmaster/interrupt.c
+++ b/src/backend/postmaster/interrupt.c
@@ -43,6 +43,10 @@ HandleMainLoopInterrupts(void)
if (ShutdownRequestPending)
proc_exit(0);
+
+ /* Process logging backtrace */
+ if (LogBacktracePending)
+ ProcessLogBacktraceInterrupt();
}
/*
diff --git a/src/backend/postmaster/pgarch.c b/src/backend/postmaster/pgarch.c
index 3b33e01d95..938c08b0eb 100644
--- a/src/backend/postmaster/pgarch.c
+++ b/src/backend/postmaster/pgarch.c
@@ -856,4 +856,8 @@ HandlePgArchInterrupts(void)
ConfigReloadPending = false;
ProcessConfigFile(PGC_SIGHUP);
}
+
+ /* Process logging backtrace */
+ if (LogBacktracePending)
+ ProcessLogBacktraceInterrupt();
}
diff --git a/src/backend/postmaster/startup.c b/src/backend/postmaster/startup.c
index 47ec737888..41d40358bf 100644
--- a/src/backend/postmaster/startup.c
+++ b/src/backend/postmaster/startup.c
@@ -200,6 +200,10 @@ HandleStartupProcInterrupts(void)
/* Process barrier events */
if (ProcSignalBarrierPending)
ProcessProcSignalBarrier();
+
+ /* Process logging backtrace */
+ if (LogBacktracePending)
+ ProcessLogBacktraceInterrupt();
}
diff --git a/src/backend/postmaster/walwriter.c b/src/backend/postmaster/walwriter.c
index 626fae8454..8bc404d17b 100644
--- a/src/backend/postmaster/walwriter.c
+++ b/src/backend/postmaster/walwriter.c
@@ -306,4 +306,8 @@ HandleWalWriterInterrupts(void)
proc_exit(0);
}
+
+ /* Process logging backtrace */
+ if (LogBacktracePending)
+ ProcessLogBacktraceInterrupt();
}
diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c
index 3dac4a8f4b..e70bfce0bd 100644
--- a/src/backend/storage/ipc/procsignal.c
+++ b/src/backend/storage/ipc/procsignal.c
@@ -633,8 +633,7 @@ HandleLogBacktraceInterrupt(void)
*
* Any backend that participates in ProcSignal signaling must arrange
* to call this function if we see LogBacktracePending set.
- * It is called from CHECK_FOR_INTERRUPTS(), which is enough because
- * the target process for logging of backtrace is a backend.
+ * CHECK_FOR_INTERRUPTS() or from process specific interrupt handlers.
*/
void
ProcessLogBacktraceInterrupt(void)
diff --git a/src/backend/storage/ipc/signalfuncs.c b/src/backend/storage/ipc/signalfuncs.c
index d042feefee..21441c64b8 100644
--- a/src/backend/storage/ipc/signalfuncs.c
+++ b/src/backend/storage/ipc/signalfuncs.c
@@ -312,29 +312,44 @@ pg_log_backtrace(PG_FUNCTION_ARGS)
#ifdef HAVE_BACKTRACE_SYMBOLS
int pid = PG_GETARG_INT32(0);
PGPROC *proc;
+ PGPROC *aux_proc = NULL;
+ BackendId backendId = InvalidBackendId;
/*
- * BackendPidGetProc returns 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 running and consuming lots of CPU cycles, that it might
- * end on its own first and its backtrace are not logged is not a problem.
+ * BackendPidGetProc or AuxiliaryPidGetProc returns 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 running and consuming lots
+ * of CPU cycles, that it might end on its own first and its backtrace are
+ * not logged is not a problem.
*/
proc = BackendPidGetProc(pid);
if (proc == NULL)
{
- ereport(WARNING,
- (errmsg("PID %d is not a PostgreSQL server process", pid)));
- PG_RETURN_BOOL(false);
+ /* See if the process with given pid is an auxiliary process. */
+ aux_proc = AuxiliaryPidGetProc(pid);
+ if (aux_proc == NULL)
+ {
+ ereport(WARNING,
+ (errmsg("PID %d is not a PostgreSQL server process", pid)));
+ PG_RETURN_BOOL(false);
+ }
}
+ /*
+ * Only regular backends will have valid backend id, auxiliary processes
+ * don't.
+ */
+ if (!aux_proc)
+ backendId = proc->backendId;
+
/*
* Send SIGUSR1 to postgres backend whose pid matches pid by
* setting PROCSIG_LOG_BACKTRACE, the backend process will log
* the backtrace once the signal is received.
*/
- if (!SendProcSignal(pid, PROCSIG_LOG_BACKTRACE, proc->backendId))
+ if (!SendProcSignal(pid, PROCSIG_LOG_BACKTRACE, backendId))
PG_RETURN_BOOL(true);
else
ereport(WARNING,
diff --git a/src/test/regress/expected/backtrace.out b/src/test/regress/expected/backtrace.out
index 88ee383d4d..52aec7088c 100644
--- a/src/test/regress/expected/backtrace.out
+++ b/src/test/regress/expected/backtrace.out
@@ -12,6 +12,17 @@ SELECT pg_log_backtrace(pg_backend_pid());
t
(1 row)
+CREATE FUNCTION get_proc_pid(text)
+RETURNS int
+LANGUAGE SQL
+AS 'SELECT pid FROM pg_stat_activity WHERE backend_type = $1';
+SELECT pg_log_backtrace(get_proc_pid('checkpointer'));
+ pg_log_backtrace
+------------------
+ t
+(1 row)
+
+DROP FUNCTION get_proc_pid(text);
CREATE ROLE regress_log_backtrace;
SELECT has_function_privilege('regress_log_backtrace',
'pg_log_backtrace(integer)', 'EXECUTE'); -- no
diff --git a/src/test/regress/expected/backtrace_1.out b/src/test/regress/expected/backtrace_1.out
index 62beef8f51..cfe51e1329 100644
--- a/src/test/regress/expected/backtrace_1.out
+++ b/src/test/regress/expected/backtrace_1.out
@@ -14,6 +14,19 @@ HINT: You need to rebuild PostgreSQL using library containing backtrace_symbols
f
(1 row)
+CREATE FUNCTION get_proc_pid(text)
+RETURNS int
+LANGUAGE SQL
+AS 'SELECT pid FROM pg_stat_activity WHERE backend_type = $1';
+SELECT pg_log_backtrace(get_proc_pid('checkpointer'));
+WARNING: backtrace generation is not supported by this installation
+HINT: You need to rebuild PostgreSQL using library containing backtrace_symbols.
+ pg_log_backtrace
+------------------
+ f
+(1 row)
+
+DROP FUNCTION get_proc_pid(text);
CREATE ROLE regress_log_backtrace;
SELECT has_function_privilege('regress_log_backtrace',
'pg_log_backtrace(integer)', 'EXECUTE'); -- no
diff --git a/src/test/regress/sql/backtrace.sql b/src/test/regress/sql/backtrace.sql
index 2688bc7330..11f52c7d29 100644
--- a/src/test/regress/sql/backtrace.sql
+++ b/src/test/regress/sql/backtrace.sql
@@ -9,6 +9,15 @@
SELECT pg_log_backtrace(pg_backend_pid());
+CREATE FUNCTION get_proc_pid(text)
+RETURNS int
+LANGUAGE SQL
+AS 'SELECT pid FROM pg_stat_activity WHERE backend_type = $1';
+
+SELECT pg_log_backtrace(get_proc_pid('checkpointer'));
+
+DROP FUNCTION get_proc_pid(text);
+
CREATE ROLE regress_log_backtrace;
SELECT has_function_privilege('regress_log_backtrace',
--
2.30.2