From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Yuriy Grigoryev <ju.grigorev@ftdata.ru>
Date: Mon, 7 Sep 2026 21:44:22 +0700
Subject: [PATCH] Clean up pgstats hash entry after restore OOM

pgstat_init_entry() can fail to allocate the DSA object after the shared
hash entry has been inserted.  Its caller in pgstat_read_statsfile()
released the hash lock before reporting the allocation failure, leaving
an entry whose body is InvalidDsaPointer.

Delete the incomplete entry before raising ERROR, as the other caller in
pgstat_get_entry_ref() already does.  dshash_delete_entry() releases the
partition lock, so release it explicitly only after successful
initialization.
---
 src/backend/utils/activity/pgstat.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/src/backend/utils/activity/pgstat.c b/src/backend/utils/activity/pgstat.c
index 4615f610106..6030f6a08de 100644
--- a/src/backend/utils/activity/pgstat.c
+++ b/src/backend/utils/activity/pgstat.c
@@ -2109,7 +2109,6 @@ pgstat_read_statsfile(void)
 					}
 
 					header = pgstat_init_entry(key.kind, p);
-					dshash_release_lock(pgStatLocal.shared_hash, p);
 					if (header == NULL)
 					{
 						/*
@@ -2117,10 +2116,12 @@ pgstat_read_statsfile(void)
 						 * WARNING, but it would mean that all the statistics
 						 * are discarded when the environment fails on OOM.
 						 */
+						dshash_delete_entry(pgStatLocal.shared_hash, p);
 						elog(ERROR, "could not allocate entry %u/%u/%" PRIu64 " of type %c",
 							 key.kind, key.dboid,
 							 key.objid, t);
 					}
+					dshash_release_lock(pgStatLocal.shared_hash, p);
 
 					if (!read_chunk(fpin,
 									pgstat_get_entry_data(key.kind, header),
