From 790fbda902093c71ae47bff1414799cd716abb80 Mon Sep 17 00:00:00 2001 From: Fujii Masao Date: Tue, 11 Jan 2022 23:19:59 +0900 Subject: [PATCH] Enhance pg_log_backend_memory_contexts() for auxiliary processes. Previously pg_log_backend_memory_contexts() could request to log the memory contexts of backends, but not of auxiliary processes such as checkpointer. This commit enhances the function so that it can also send the request to auxiliary processes. It's useful to look at the memory contexts of those processes for debugging purpose and better understanding of the memory usage pattern of them. Note that pg_log_backend_memory_contexts() cannot send the request to logger or statistics collector. Because this logging request mechanism is based on shared memory but those processes aren't connected to that. Author: Bharath Rupireddy Reviewed-by: Vignesh C, Kyotaro Horiguchi, Fujii Masao Discussion: https://postgr.es/m/CALj2ACU1nBzpacOK2q=a65S_4+Oaz_rLTsU1Ri0gf7YUmnmhfQ@mail.gmail.com --- doc/src/sgml/func.sgml | 4 ++- src/backend/postmaster/checkpointer.c | 4 +++ src/backend/postmaster/interrupt.c | 5 +++ src/backend/postmaster/pgarch.c | 10 ++++-- src/backend/postmaster/startup.c | 5 +++ src/backend/postmaster/walwriter.c | 4 +++ src/backend/utils/adt/mcxtfuncs.c | 38 +++++++++++++------- src/test/regress/expected/misc_functions.out | 7 ++++ src/test/regress/sql/misc_functions.sql | 3 ++ 9 files changed, 65 insertions(+), 15 deletions(-) diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml index e58efce586..391d01bcf3 100644 --- a/doc/src/sgml/func.sgml +++ b/doc/src/sgml/func.sgml @@ -25421,7 +25421,9 @@ SELECT collation for ('foo' COLLATE "de_DE"); Requests to log the memory contexts of the backend with the - specified process ID. These memory contexts will be logged at + specified process ID. This function can send the request to + backends and auxiliary processes except logger and statistics + collector. These memory contexts will be logged at LOG message level. They will appear in the server log based on the log configuration set (See for more information), diff --git a/src/backend/postmaster/checkpointer.c b/src/backend/postmaster/checkpointer.c index 940b773fe1..23f691cd47 100644 --- a/src/backend/postmaster/checkpointer.c +++ b/src/backend/postmaster/checkpointer.c @@ -577,6 +577,10 @@ HandleCheckpointerInterrupts(void) /* Normal exit from the checkpointer is here */ proc_exit(0); /* done */ } + + /* Perform logging of memory contexts of this process */ + if (LogMemoryContextPending) + ProcessLogMemoryContextInterrupt(); } /* diff --git a/src/backend/postmaster/interrupt.c b/src/backend/postmaster/interrupt.c index b3db4f2a4c..3f412dad2e 100644 --- a/src/backend/postmaster/interrupt.c +++ b/src/backend/postmaster/interrupt.c @@ -22,6 +22,7 @@ #include "storage/latch.h" #include "storage/procsignal.h" #include "utils/guc.h" +#include "utils/memutils.h" volatile sig_atomic_t ConfigReloadPending = false; volatile sig_atomic_t ShutdownRequestPending = false; @@ -43,6 +44,10 @@ HandleMainLoopInterrupts(void) if (ShutdownRequestPending) proc_exit(0); + + /* Perform logging of memory contexts of this process */ + if (LogMemoryContextPending) + ProcessLogMemoryContextInterrupt(); } /* diff --git a/src/backend/postmaster/pgarch.c b/src/backend/postmaster/pgarch.c index b319d03290..1121e4fb29 100644 --- a/src/backend/postmaster/pgarch.c +++ b/src/backend/postmaster/pgarch.c @@ -50,6 +50,7 @@ #include "storage/shmem.h" #include "storage/spin.h" #include "utils/guc.h" +#include "utils/memutils.h" #include "utils/ps_status.h" @@ -861,8 +862,9 @@ pgarch_die(int code, Datum arg) * Interrupt handler for WAL archiver process. * * This is called in the loops pgarch_MainLoop and pgarch_ArchiverCopyLoop. - * It checks for barrier events and config update, but not shutdown request - * because how to handle shutdown request is different between those loops. + * It checks for barrier events, config update and request for logging of + * memory contexts, but not shutdown request because how to handle + * shutdown request is different between those loops. */ static void HandlePgArchInterrupts(void) @@ -875,4 +877,8 @@ HandlePgArchInterrupts(void) ConfigReloadPending = false; ProcessConfigFile(PGC_SIGHUP); } + + /* Perform logging of memory contexts of this process */ + if (LogMemoryContextPending) + ProcessLogMemoryContextInterrupt(); } diff --git a/src/backend/postmaster/startup.c b/src/backend/postmaster/startup.c index e9518beedc..9bae16bfc7 100644 --- a/src/backend/postmaster/startup.c +++ b/src/backend/postmaster/startup.c @@ -32,6 +32,7 @@ #include "storage/procsignal.h" #include "storage/standby.h" #include "utils/guc.h" +#include "utils/memutils.h" #include "utils/timeout.h" @@ -200,6 +201,10 @@ HandleStartupProcInterrupts(void) /* Process barrier events */ if (ProcSignalBarrierPending) ProcessProcSignalBarrier(); + + /* Perform logging of memory contexts of this process */ + if (LogMemoryContextPending) + ProcessLogMemoryContextInterrupt(); } diff --git a/src/backend/postmaster/walwriter.c b/src/backend/postmaster/walwriter.c index 9db9d98653..102fa2a089 100644 --- a/src/backend/postmaster/walwriter.c +++ b/src/backend/postmaster/walwriter.c @@ -306,4 +306,8 @@ HandleWalWriterInterrupts(void) proc_exit(0); } + + /* Perform logging of memory contexts of this process */ + if (LogMemoryContextPending) + ProcessLogMemoryContextInterrupt(); } diff --git a/src/backend/utils/adt/mcxtfuncs.c b/src/backend/utils/adt/mcxtfuncs.c index 845d619d60..28cb9d3ff1 100644 --- a/src/backend/utils/adt/mcxtfuncs.c +++ b/src/backend/utils/adt/mcxtfuncs.c @@ -160,33 +160,47 @@ pg_get_backend_memory_contexts(PG_FUNCTION_ARGS) /* * pg_log_backend_memory_contexts - * Signal a backend process to log its memory contexts. + * Signal a backend or an auxiliary process to log its memory contexts. * * By default, only superusers are allowed to signal to log the memory * contexts because allowing any users to issue this request at an unbounded * rate would cause lots of log messages and which can lead to denial of * service. Additional roles can be permitted with GRANT. * - * On receipt of this signal, a backend sets the flag in the signal - * handler, which causes the next CHECK_FOR_INTERRUPTS() to log the - * memory contexts. + * On receipt of this signal, a backend or an auxiliary process sets the flag + * in the signal handler, which causes the next CHECK_FOR_INTERRUPTS() + * or process-specific interrupt handler to log the memory contexts. */ Datum pg_log_backend_memory_contexts(PG_FUNCTION_ARGS) { int pid = PG_GETARG_INT32(0); PGPROC *proc; + BackendId backendId = InvalidBackendId; proc = BackendPidGetProc(pid); /* - * 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 memory, that it - * might end on its own first and its memory contexts are not logged is - * not a problem. + * See if the process with given pid is a backend or an auxiliary process. + * + * 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) { @@ -199,7 +213,7 @@ pg_log_backend_memory_contexts(PG_FUNCTION_ARGS) PG_RETURN_BOOL(false); } - if (SendProcSignal(pid, PROCSIG_LOG_MEMORY_CONTEXT, proc->backendId) < 0) + if (SendProcSignal(pid, PROCSIG_LOG_MEMORY_CONTEXT, 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 1013d17f87..e2c77d0ac8 100644 --- a/src/test/regress/expected/misc_functions.out +++ b/src/test/regress/expected/misc_functions.out @@ -147,6 +147,13 @@ SELECT pg_log_backend_memory_contexts(pg_backend_pid()); t (1 row) +SELECT pg_log_backend_memory_contexts(pid) FROM pg_stat_activity + WHERE backend_type = 'checkpointer'; + pg_log_backend_memory_contexts +-------------------------------- + t +(1 row) + CREATE ROLE regress_log_memory; SELECT has_function_privilege('regress_log_memory', 'pg_log_backend_memory_contexts(integer)', 'EXECUTE'); -- no diff --git a/src/test/regress/sql/misc_functions.sql b/src/test/regress/sql/misc_functions.sql index 7ab9b2a150..1159f6b585 100644 --- a/src/test/regress/sql/misc_functions.sql +++ b/src/test/regress/sql/misc_functions.sql @@ -41,6 +41,9 @@ SELECT num_nulls(); SELECT pg_log_backend_memory_contexts(pg_backend_pid()); +SELECT pg_log_backend_memory_contexts(pid) FROM pg_stat_activity + WHERE backend_type = 'checkpointer'; + CREATE ROLE regress_log_memory; SELECT has_function_privilege('regress_log_memory',