Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1vIWGb-0041AO-0Z for pgsql-hackers@arkaria.postgresql.org; Mon, 10 Nov 2025 18:05:24 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1vIWGX-001tck-15 for pgsql-hackers@arkaria.postgresql.org; Mon, 10 Nov 2025 18:05:21 +0000 Received: from makus.postgresql.org ([2001:4800:3e1:1::229]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1vIWGW-001tcc-2l for pgsql-hackers@lists.postgresql.org; Mon, 10 Nov 2025 18:05:21 +0000 Received: from mail-il1-x12c.google.com ([2607:f8b0:4864:20::12c]) by makus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.96) (envelope-from ) id 1vIWGU-006Ppy-2f for pgsql-hackers@postgresql.org; Mon, 10 Nov 2025 18:05:19 +0000 Received: by mail-il1-x12c.google.com with SMTP id e9e14a558f8ab-4335726d0f2so12916835ab.1 for ; Mon, 10 Nov 2025 10:05:18 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1762797917; x=1763402717; darn=postgresql.org; h=in-reply-to:content-disposition:mime-version:references:message-id :subject:cc:to:from:date:from:to:cc:subject:date:message-id:reply-to; bh=NygN227p2vPPh7iyEVtbso3BAay9mW2w5uQlRJY0JO8=; b=JwAQHw1Vc1HS4yvGNVWtauCV3CAhff8Uye3rFb/VU0Wc4oym7b1MDMsLHRytPwJhXm cyy7GXWnQRB/9MN/i8KgVjoYhet+5sk0f73hoM/MWHxp7/33TtzKKhLdhiDt4msZ33m4 gSD/6xsAKVGmZtbHmVOHprjYPzSuBgfRjyF7I43aREEbuTY4SO1XGRL3X/O+z6Bl63JL Hg4QsZW4qlOfYk+JYFjY7zQBAQT7/F2digQ9DsmSxyyDOpfmlP6QHzt0JTBzog7u53QN 6HuPuFvEgioVTDRxwvfiXtt+EM0WDheDVpZYJbv+vGfCojBW02mvYbqwhbR4wA/lRZAl imNA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1762797917; x=1763402717; h=in-reply-to:content-disposition:mime-version:references:message-id :subject:cc:to:from:date:x-gm-gg:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=NygN227p2vPPh7iyEVtbso3BAay9mW2w5uQlRJY0JO8=; b=dRGvxxbSTiiw0GMx2Qwnvkj5k/0/AKZrejPTwzWMsjeJTUJEJlGG4VnxExIiZeXJLw sNrjcpc/xJd+aYKqDgovGfGH9eDSXQv/NCb+DhjLlOzjO8Yi8A6KWUBefcqykbw4bqqe TCBQU+J7ejYeF5DEc48oLMKbVg1Q+z7XBJTaahEqbeQ+2xc4CEwqKgnel4QbbwlnB3SH EvEQBvk8c3H2j663z7E+e1aJFdqqRqVPRdrFtDgCvFKp03WXX1T5pXCDCF+J2TWZkYDZ GPX5n2Tocp3RW5M5ZGxO5tIF0HSeRpO+j82+LRuKwXJTJygH+1Z3cOwavlrtO3ETXcwf hw2Q== X-Forwarded-Encrypted: i=1; AJvYcCXg/G2zTRHIOzktFYSrMvncZQ+08CYU7zg9APYH0lxaQYRBQ3YNAbnvvJvgqt9GTseR6EmRJNP13TDe6qlO@postgresql.org X-Gm-Message-State: AOJu0YxyiWmkM5cb/zw0+kwLpXn5nz1CsoQNKm60uE3wqGFbW1yZjUoR v6YfPCt17qR/7xaXrTHdLbJJptGbh3SLIbmuyDM2/5rsyVOKsJ1OmK7j X-Gm-Gg: ASbGncu/UmpVUJ+46b13WfhklLXPSbbu8gkqdvOH+Yy+hG76LUsDFb4s7jYIhK8kd4N pAX7r1jWX/zHzb3y6eT1zr798SQ3RYtGgHzFFVrvOlFXzbkLzk6qXZQ9oNFBwfCZteXG6XQyDME LrrFvz2Y7+Li6gVYSzjb8pbngbIlqqeH+H80mbujNwWPmxyBH1o2aQBg2O0MX+WCNCrtr9RXX6Y 0Kno4RuDFQY0iPHXgHQ+lk2MAueRS0ChR8FQsESxx2Im4x+6Xr/Y76AAYeKGjOOsSbRkcnNoJpZ GB08Geqrezy7g7TVVf/UFHxE4uiirZmoePb5tKuCYscPxLUJKY9fFIzMps+2vKJeWPxmvsbED/+ IBayAmTYW/m3kgrscOlYrJ8KAcSsrSs/OdmFLrho1/ISCHr3+i6zHi5b7ZKbVhbEb4xKWJgBQoT dlPeosxvHIJyZsQpWW/UYkcPRgDyMxBR/yIpEcwWp5W4QyLesnUquBzXP7rpCTjw+BoA== X-Google-Smtp-Source: AGHT+IFg7dQO25nKoZcJWk2mXhONmkMn6ZIhfZHKSdXJYetiOJzkEnqXZBUBU2R225AS+aanmMBvzw== X-Received: by 2002:a05:6e02:b29:b0:433:3102:b0f5 with SMTP id e9e14a558f8ab-43367e670e9mr114059895ab.30.1762797917369; Mon, 10 Nov 2025 10:05:17 -0800 (PST) Received: from nathan (162-195-168-172.lightspeed.stlsmo.sbcglobal.net. [162.195.168.172]) by smtp.gmail.com with ESMTPSA id e9e14a558f8ab-4334f45c7d9sm60195005ab.16.2025.11.10.10.05.16 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 10 Nov 2025 10:05:16 -0800 (PST) Date: Mon, 10 Nov 2025 12:05:14 -0600 From: Nathan Bossart To: Sami Imseih Cc: Alexander Lakhin , Rahila Syed , Bertrand Drouvot , Tom Lane , Andres Freund , pgsql-hackers Subject: Re: Improve LWLock tranche name visibility across backends Message-ID: References: MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="DWDGkHIbZGie56xR" Content-Disposition: inline In-Reply-To: List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk --DWDGkHIbZGie56xR Content-Type: text/plain; charset=us-ascii Content-Disposition: inline On Mon, Nov 10, 2025 at 10:49:58AM -0600, Nathan Bossart wrote: > On Mon, Nov 10, 2025 at 10:26:17AM -0600, Nathan Bossart wrote: >> It's probably a good idea to avoid tranche leaks, but IMHO there's room for >> improvement in the DSM registry, too. IIUC the problem is that the DSM >> segment is still being added to the registry and found by other backends >> despite the initialization callback failing. My first instinct is that we >> should keep track of whether the DSM segments/DSAs/dshash tables in the >> registry have been fully initialized and to just ERROR in other backends >> when attaching if they aren't. That shouldn't really happen in practice, >> but it'd be good to avoid the strange errors, anyway. 0001 does this. When applied, Alexander's reproduction steps fail with ERROR: requested DSM segment failed initialization This one should probably get back-patched to v17, where the DSM registry was introduced. > BTW if we really wanted to avoid leaking tranches in test_dsa, we'd need to > store the ID in shared memory. Your patch helps in the case where a single > backend is repeatedly calling test_dsa_resowners(), but other backends > would still allocate their own tranche. I don't see a strong need to fix > this on back-branches, given these functions run exactly once as part of a > test, but fixing it on master seems worthwhile so that extension authors > don't copy/paste this broken code. 0002 does this. -- nathan --DWDGkHIbZGie56xR Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v2-0001-DSM-registry-ERROR-if-entry-was-not-initialized.patch From 0b4ccd2fd0393ed43edf39f018b2dabd9ca2b001 Mon Sep 17 00:00:00 2001 From: Nathan Bossart Date: Mon, 10 Nov 2025 11:43:51 -0600 Subject: [PATCH v2 1/2] DSM registry: ERROR if entry was not initialized. --- src/backend/storage/ipc/dsm_registry.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/backend/storage/ipc/dsm_registry.c b/src/backend/storage/ipc/dsm_registry.c index a926b9c3f32..ec8b48ad9a0 100644 --- a/src/backend/storage/ipc/dsm_registry.c +++ b/src/backend/storage/ipc/dsm_registry.c @@ -93,6 +93,7 @@ typedef struct DSMRegistryEntry { char name[NAMEDATALEN]; DSMREntryType type; + bool initialized; union { NamedDSMState dsm; @@ -216,6 +217,7 @@ GetNamedDSMSegment(const char *name, size_t size, dsm_segment *seg; entry->type = DSMR_ENTRY_TYPE_DSM; + entry->initialized = false; /* Initialize the segment. */ seg = dsm_create(size, 0); @@ -228,7 +230,12 @@ GetNamedDSMSegment(const char *name, size_t size, if (init_callback) (*init_callback) (ret); + + entry->initialized = true; } + else if (!entry->initialized) + ereport(ERROR, + (errmsg("requested DSM segment failed initialization"))); else if (entry->type != DSMR_ENTRY_TYPE_DSM) ereport(ERROR, (errmsg("requested DSM segment does not match type of existing entry"))); @@ -297,6 +304,7 @@ GetNamedDSA(const char *name, bool *found) NamedDSAState *state = &entry->dsa; entry->type = DSMR_ENTRY_TYPE_DSA; + entry->initialized = false; /* Initialize the LWLock tranche for the DSA. */ state->tranche = LWLockNewTrancheId(name); @@ -308,7 +316,12 @@ GetNamedDSA(const char *name, bool *found) /* Store handle for other backends to use. */ state->handle = dsa_get_handle(ret); + + entry->initialized = true; } + else if (!entry->initialized) + ereport(ERROR, + (errmsg("requested DSA failed initialization"))); else if (entry->type != DSMR_ENTRY_TYPE_DSA) ereport(ERROR, (errmsg("requested DSA does not match type of existing entry"))); @@ -372,6 +385,7 @@ GetNamedDSHash(const char *name, const dshash_parameters *params, bool *found) dsa_area *dsa; entry->type = DSMR_ENTRY_TYPE_DSH; + entry->initialized = false; /* Initialize the LWLock tranche for the hash table. */ dsh_state->tranche = LWLockNewTrancheId(name); @@ -389,7 +403,12 @@ GetNamedDSHash(const char *name, const dshash_parameters *params, bool *found) /* 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); + + entry->initialized = true; } + else if (!entry->initialized) + ereport(ERROR, + (errmsg("requested DSHash failed initialization"))); else if (entry->type != DSMR_ENTRY_TYPE_DSH) ereport(ERROR, (errmsg("requested DSHash does not match type of existing entry"))); -- 2.39.5 (Apple Git-154) --DWDGkHIbZGie56xR Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v2-0002-test_dsa-Avoid-leaking-LWLock-tranches.patch From 37ef7e1fd21cc1aa93cdc1af4fd84a26516faaa3 Mon Sep 17 00:00:00 2001 From: Nathan Bossart Date: Mon, 10 Nov 2025 12:03:47 -0600 Subject: [PATCH v2 2/2] test_dsa: Avoid leaking LWLock tranches. --- src/test/modules/test_dsa/test_dsa.c | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/src/test/modules/test_dsa/test_dsa.c b/src/test/modules/test_dsa/test_dsa.c index 01d5c6fa67f..21e4ce6a745 100644 --- a/src/test/modules/test_dsa/test_dsa.c +++ b/src/test/modules/test_dsa/test_dsa.c @@ -13,25 +13,35 @@ #include "postgres.h" #include "fmgr.h" +#include "storage/dsm_registry.h" #include "storage/lwlock.h" #include "utils/dsa.h" #include "utils/resowner.h" PG_MODULE_MAGIC; +static void +init_tranche(void *ptr) +{ + int *tranche_id = (int *) ptr; + + *tranche_id = LWLockNewTrancheId("test_dsa"); +} + /* Test basic DSA functionality */ PG_FUNCTION_INFO_V1(test_dsa_basic); Datum test_dsa_basic(PG_FUNCTION_ARGS) { - int tranche_id; + int *tranche_id; + bool found; dsa_area *a; dsa_pointer p[100]; - /* XXX: this tranche is leaked */ - tranche_id = LWLockNewTrancheId("test_dsa"); + tranche_id = GetNamedDSMSegment("test_dsa", sizeof(int), + init_tranche, &found); - a = dsa_create(tranche_id); + a = dsa_create(*tranche_id); for (int i = 0; i < 100; i++) { p[i] = dsa_allocate(a, 1000); @@ -62,17 +72,18 @@ PG_FUNCTION_INFO_V1(test_dsa_resowners); Datum test_dsa_resowners(PG_FUNCTION_ARGS) { - int tranche_id; + int *tranche_id; + bool found; dsa_area *a; dsa_pointer p[10000]; ResourceOwner oldowner; ResourceOwner childowner; - /* XXX: this tranche is leaked */ - tranche_id = LWLockNewTrancheId("test_dsa"); + tranche_id = GetNamedDSMSegment("test_dsa", sizeof(int), + init_tranche, &found); /* Create DSA in parent resource owner */ - a = dsa_create(tranche_id); + a = dsa_create(*tranche_id); /* * Switch to child resource owner, and do a bunch of allocations in the -- 2.39.5 (Apple Git-154) --DWDGkHIbZGie56xR--