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

---
 src/backend/storage/ipc/dsm_registry.c | 129 ++++++++++++++++++++++---
 1 file changed, 115 insertions(+), 14 deletions(-)

diff --git a/src/backend/storage/ipc/dsm_registry.c b/src/backend/storage/ipc/dsm_registry.c
index a926b9c3f32..7d1b584d166 100644
--- a/src/backend/storage/ipc/dsm_registry.c
+++ b/src/backend/storage/ipc/dsm_registry.c
@@ -154,10 +154,24 @@ init_dsm_registry(void)
 	if (DSMRegistryCtx->dshh == DSHASH_HANDLE_INVALID)
 	{
 		/* Initialize dynamic shared hash table for registry. */
-		dsm_registry_dsa = dsa_create(LWTRANCHE_DSM_REGISTRY_DSA);
+		PG_TRY();
+		{
+			dsm_registry_dsa = dsa_create(LWTRANCHE_DSM_REGISTRY_DSA);
+			dsm_registry_table = dshash_create(dsm_registry_dsa, &dsh_params, NULL);
+		}
+		PG_CATCH();
+		{
+			if (dsm_registry_dsa)
+			{
+				dsa_detach(dsm_registry_dsa);
+				dsm_registry_dsa = NULL;
+			}
+			PG_RE_THROW();
+		}
+		PG_END_TRY();
+
 		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);
@@ -216,18 +230,38 @@ GetNamedDSMSegment(const char *name, size_t size,
 		dsm_segment *seg;
 
 		entry->type = DSMR_ENTRY_TYPE_DSM;
+		state->handle = DSM_HANDLE_INVALID;
 
 		/* Initialize the segment. */
-		seg = dsm_create(size, 0);
+		PG_TRY();
+		{
+			seg = dsm_create(size, 0);
+		}
+		PG_CATCH();
+		{
+			dshash_delete_entry(dsm_registry_table, entry);
+			PG_RE_THROW();
+		}
+		PG_END_TRY();
+
+		PG_TRY();
+		{
+			ret = dsm_segment_address(seg);
+			if (init_callback)
+				(*init_callback) (ret);
+		}
+		PG_CATCH();
+		{
+			dsm_detach(seg);
+			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,9 +331,19 @@ 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);
@@ -312,6 +356,16 @@ 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;
+
+		ret = dsa_create(state->tranche);
+
+		dsa_pin(ret);
+		dsa_pin_mapping(ret);
+		state->handle = dsa_get_handle(ret);
+	}
 	else
 	{
 		NamedDSAState *state = &entry->dsa;
@@ -372,19 +426,40 @@ 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;
+		dsh_state->dsh_handle = DSHASH_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);
+		PG_TRY();
+		{
+			memcpy(&params_copy, params, sizeof(dshash_parameters));
+			params_copy.tranche_id = dsh_state->tranche;
+			ret = dshash_create(dsa, &params_copy, NULL);
+		}
+		PG_CATCH();
+		{
+			dsa_detach(dsa);
+			PG_RE_THROW();
+		}
+		PG_END_TRY();
+
+		dsa_pin(dsa);
+		dsa_pin_mapping(dsa);
 
 		/* Store handles for other backends to use. */
 		dsh_state->dsa_handle = dsa_get_handle(dsa);
@@ -393,6 +468,32 @@ 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;
+
+		dsa = dsa_create(dsh_state->tranche);
+
+		PG_TRY();
+		{
+			memcpy(&params_copy, params, sizeof(dshash_parameters));
+			params_copy.tranche_id = dsh_state->tranche;
+			ret = dshash_create(dsa, &params_copy, NULL);
+		}
+		PG_CATCH();
+		{
+			dsa_detach(dsa);
+			PG_RE_THROW();
+		}
+		PG_END_TRY();
+
+		dsa_pin(dsa);
+		dsa_pin_mapping(dsa);
+		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)

