From 4ff6890214be7c175b479a9842a7fdd42fc6ad20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anders=20=C3=85strand?= Date: Mon, 25 May 2026 10:38:06 +0200 Subject: [PATCH] Fetch datname and username from syscache in pgsm_store() Resolve them from the catalog in pgsm_store() rather than in pgsm_create_hash_entry(). We have a bug report we have not been able to reproduce where queryDesc->totaltime is freed mid-call in pgsm_ExecutorEnd(), most likely by cache invalidation processing during these syscache lookups when they ran inside pgsm_create_hash_entry(). The misbehaving callback is most likely from another extension or the RDS fork of PostgreSQL, since standard invalidation callbacks does not seem to touch the relevant memory context. --- pg_stat_monitor.c | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/pg_stat_monitor.c b/pg_stat_monitor.c index 5ebe348a..9e921762 100644 --- a/pg_stat_monitor.c +++ b/pg_stat_monitor.c @@ -1695,8 +1695,6 @@ pgsm_create_hash_entry(uint64 bucket_id, int64 queryid, PlanInfo *plan_info) int sec_ctx; bool found_client_addr = false; MemoryContext oldctx; - char *datname = NULL; - char *username = NULL; /* Create an entry in the pgsm memory context */ oldctx = MemoryContextSwitchTo(GetPgsmMemoryContext()); @@ -1736,21 +1734,6 @@ pgsm_create_hash_entry(uint64 bucket_id, int64 queryid, PlanInfo *plan_info) entry->key.toplevel = ((nesting_level + plan_nested_level) == 0); #endif - if (IsTransactionState()) - { - datname = get_database_name(entry->key.dbid); - username = GetUserNameFromId(entry->key.userid, true); - - snprintf(entry->datname, sizeof(entry->datname), "%s", datname); - snprintf(entry->username, sizeof(entry->username), "%s", username); - - if (datname) - pfree(datname); - - if (username) - pfree(username); - } - MemoryContextSwitchTo(oldctx); return entry; @@ -1804,6 +1787,23 @@ pgsm_store(pgsmEntry *entry) extract_query_comments(query, comments, sizeof(comments)); comments_len = strlen(comments); + if (IsTransactionState() && strlen(entry->datname) == 0) + { + char *datname = get_database_name(entry->key.dbid); + + snprintf(entry->datname, sizeof(entry->datname), "%s", datname); + if (datname) + pfree(datname); + } + if (IsTransactionState() && strlen(entry->username) == 0) + { + char *username = GetUserNameFromId(entry->key.userid, true); + + snprintf(entry->username, sizeof(entry->username), "%s", username); + if (username) + pfree(username); + } + /* bufusage */ bufusage.shared_blks_hit = entry->counters.blocks.shared_blks_hit; bufusage.shared_blks_read = entry->counters.blocks.shared_blks_read;