From 3529f2e17b85537198d8a6fa783ca9c0b0522547 Mon Sep 17 00:00:00 2001
From: Nathan Bossart <nathan@postgresql.org>
Date: Mon, 24 Nov 2025 12:28:23 -0600
Subject: [PATCH v2 2/2] handle ERRORs in DSM registry functions

---
 src/backend/storage/ipc/dsm_registry.c | 85 +++++++++++++++++++++++---
 1 file changed, 75 insertions(+), 10 deletions(-)

diff --git a/src/backend/storage/ipc/dsm_registry.c b/src/backend/storage/ipc/dsm_registry.c
index a926b9c3f32..bae67d15add 100644
--- a/src/backend/storage/ipc/dsm_registry.c
+++ b/src/backend/storage/ipc/dsm_registry.c
@@ -155,9 +155,10 @@ init_dsm_registry(void)
 	{
 		/* Initialize dynamic shared hash table for registry. */
 		dsm_registry_dsa = dsa_create(LWTRANCHE_DSM_REGISTRY_DSA);
+		dsm_registry_table = dshash_create(dsm_registry_dsa, &dsh_params, NULL);
+
 		dsa_pin(dsm_registry_dsa);
 		dsa_pin_mapping(dsm_registry_dsa);
-		dsm_registry_table = dshash_create(dsm_registry_dsa, &dsh_params, NULL);
 
 		/* Store handles in shared memory for other backends to use. */
 		DSMRegistryCtx->dsah = dsa_get_handle(dsm_registry_dsa);
@@ -218,16 +219,24 @@ GetNamedDSMSegment(const char *name, size_t size,
 		entry->type = DSMR_ENTRY_TYPE_DSM;
 
 		/* Initialize the segment. */
-		seg = dsm_create(size, 0);
+		PG_TRY();
+		{
+			seg = dsm_create(size, 0);
+			ret = dsm_segment_address(seg);
+			if (init_callback)
+				(*init_callback) (ret);
+		}
+		PG_CATCH();
+		{
+			dshash_delete_entry(dsm_registry_table, entry);
+			PG_RE_THROW();
+		}
+		PG_END_TRY();
 
 		dsm_pin_segment(seg);
 		dsm_pin_mapping(seg);
 		state->handle = dsm_segment_handle(seg);
 		state->size = size;
-		ret = dsm_segment_address(seg);
-
-		if (init_callback)
-			(*init_callback) (ret);
 	}
 	else if (entry->type != DSMR_ENTRY_TYPE_DSM)
 		ereport(ERROR,
@@ -297,12 +306,23 @@ GetNamedDSA(const char *name, bool *found)
 		NamedDSAState *state = &entry->dsa;
 
 		entry->type = DSMR_ENTRY_TYPE_DSA;
+		state->handle = DSA_HANDLE_INVALID;
 
 		/* Initialize the LWLock tranche for the DSA. */
-		state->tranche = LWLockNewTrancheId(name);
+		PG_TRY();
+		{
+			state->tranche = LWLockNewTrancheId(name);
+		}
+		PG_CATCH();
+		{
+			dshash_delete_entry(dsm_registry_table, entry);
+			PG_RE_THROW();
+		}
+		PG_END_TRY();
 
 		/* Initialize the DSA. */
 		ret = dsa_create(state->tranche);
+
 		dsa_pin(ret);
 		dsa_pin_mapping(ret);
 
@@ -312,6 +332,19 @@ GetNamedDSA(const char *name, bool *found)
 	else if (entry->type != DSMR_ENTRY_TYPE_DSA)
 		ereport(ERROR,
 				(errmsg("requested DSA does not match type of existing entry")));
+	else if (entry->dsa.handle == DSA_HANDLE_INVALID)
+	{
+		NamedDSAState *state = &entry->dsa;
+
+		/* Initialize the DSA. */
+		ret = dsa_create(state->tranche);
+
+		dsa_pin(ret);
+		dsa_pin_mapping(ret);
+
+		/* Store handle for other backends to use. */
+		state->handle = dsa_get_handle(ret);
+	}
 	else
 	{
 		NamedDSAState *state = &entry->dsa;
@@ -372,20 +405,31 @@ GetNamedDSHash(const char *name, const dshash_parameters *params, bool *found)
 		dsa_area   *dsa;
 
 		entry->type = DSMR_ENTRY_TYPE_DSH;
+		dsh_state->dsa_handle = DSA_HANDLE_INVALID;
 
 		/* Initialize the LWLock tranche for the hash table. */
-		dsh_state->tranche = LWLockNewTrancheId(name);
+		PG_TRY();
+		{
+			dsh_state->tranche = LWLockNewTrancheId(name);
+		}
+		PG_CATCH();
+		{
+			dshash_delete_entry(dsm_registry_table, entry);
+			PG_RE_THROW();
+		}
+		PG_END_TRY();
 
 		/* Initialize the DSA for the hash table. */
 		dsa = dsa_create(dsh_state->tranche);
-		dsa_pin(dsa);
-		dsa_pin_mapping(dsa);
 
 		/* Initialize the dshash table. */
 		memcpy(&params_copy, params, sizeof(dshash_parameters));
 		params_copy.tranche_id = dsh_state->tranche;
 		ret = dshash_create(dsa, &params_copy, NULL);
 
+		dsa_pin(dsa);
+		dsa_pin_mapping(dsa);
+
 		/* Store handles for other backends to use. */
 		dsh_state->dsa_handle = dsa_get_handle(dsa);
 		dsh_state->dsh_handle = dshash_get_hash_table_handle(ret);
@@ -393,6 +437,27 @@ GetNamedDSHash(const char *name, const dshash_parameters *params, bool *found)
 	else if (entry->type != DSMR_ENTRY_TYPE_DSH)
 		ereport(ERROR,
 				(errmsg("requested DSHash does not match type of existing entry")));
+	else if (entry->dsh.dsa_handle == DSA_HANDLE_INVALID)
+	{
+		NamedDSHState *dsh_state = &entry->dsh;
+		dshash_parameters params_copy;
+		dsa_area   *dsa;
+
+		/* Initialize the DSA for the hash table. */
+		dsa = dsa_create(dsh_state->tranche);
+
+		/* Initialize the dshash table. */
+		memcpy(&params_copy, params, sizeof(dshash_parameters));
+		params_copy.tranche_id = dsh_state->tranche;
+		ret = dshash_create(dsa, &params_copy, NULL);
+
+		dsa_pin(dsa);
+		dsa_pin_mapping(dsa);
+
+		/* Store handles for other backends to use. */
+		dsh_state->dsa_handle = dsa_get_handle(dsa);
+		dsh_state->dsh_handle = dshash_get_hash_table_handle(ret);
+	}
 	else
 	{
 		NamedDSHState *dsh_state = &entry->dsh;
-- 
2.39.5 (Apple Git-154)

