</para>
<para>
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
<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),
/* Normal exit from the checkpointer is here */
proc_exit(0); /* done */
}
+
+ /* Perform logging of memory contexts of this process */
+ if (LogMemoryContextPending)
+ ProcessLogMemoryContextInterrupt();
}
/*
#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;
if (ShutdownRequestPending)
proc_exit(0);
+
+ /* Perform logging of memory contexts of this process */
+ if (LogMemoryContextPending)
+ ProcessLogMemoryContextInterrupt();
}
/*
#include "storage/shmem.h"
#include "storage/spin.h"
#include "utils/guc.h"
+#include "utils/memutils.h"
#include "utils/ps_status.h"
* 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)
ConfigReloadPending = false;
ProcessConfigFile(PGC_SIGHUP);
}
+
+ /* Perform logging of memory contexts of this process */
+ if (LogMemoryContextPending)
+ ProcessLogMemoryContextInterrupt();
}
#include "storage/procsignal.h"
#include "storage/standby.h"
#include "utils/guc.h"
+#include "utils/memutils.h"
#include "utils/timeout.h"
/* Process barrier events */
if (ProcSignalBarrierPending)
ProcessProcSignalBarrier();
+
+ /* Perform logging of memory contexts of this process */
+ if (LogMemoryContextPending)
+ ProcessLogMemoryContextInterrupt();
}
proc_exit(0);
}
+
+ /* Perform logging of memory contexts of this process */
+ if (LogMemoryContextPending)
+ ProcessLogMemoryContextInterrupt();
}
/*
* 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)
{
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,
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
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',