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.94.2) (envelope-from ) id 1uyxPc-00Eu16-9y for pgsql-hackers@arkaria.postgresql.org; Wed, 17 Sep 2025 19:01:52 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.94.2) (envelope-from ) id 1uyxOb-00ADeG-87 for pgsql-hackers@arkaria.postgresql.org; Wed, 17 Sep 2025 19:00:50 +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.94.2) (envelope-from ) id 1uyxOa-00ADe7-Mj for pgsql-hackers@lists.postgresql.org; Wed, 17 Sep 2025 19:00:49 +0000 Received: from mail-io1-xd36.google.com ([2607:f8b0:4864:20::d36]) by makus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.96) (envelope-from ) id 1uyxOY-000xAc-3D for pgsql-hackers@postgresql.org; Wed, 17 Sep 2025 19:00:48 +0000 Received: by mail-io1-xd36.google.com with SMTP id ca18e2360f4ac-89365bbc079so8865139f.0 for ; Wed, 17 Sep 2025 12:00:47 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1758135646; x=1758740446; 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=EEK6lwfrsBFxrqT+AtBzVdR8z4I+W3XaeDjjornA7cI=; b=THrSDVhIa1WVRnEXsX2YUJcVlZAm8aWa7vPJ8Kf+QXMIRRLtpRSJdd8qPxWgRZGaKd qAbspTKsCZ05St/zm48VjROUYDYXYJysggJCiU+dfB9daTrCUPHJPEWI0rRLbYCI1tXB gMYzzn+BNEkPiye+55aPPfARsZNZlyASe01hj61pdJS3z7YabFblQ4E/18uiBU0nsuAI TSJuAHz/PBGcSCPqnv0r1tvoWPFrR3kjdDvrjlgJ8fCAdMaUWuL1NqbVdwU7IHizr5P/ cfpuS0VrUEyACEix/Wyp7oeo9z2+fj8fEi39RWrfyjP59TStkk0wAW+ztrrcwQuWFlot EzdQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1758135646; x=1758740446; h=in-reply-to:content-disposition:mime-version:references:message-id :subject:cc:to:from:date:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=EEK6lwfrsBFxrqT+AtBzVdR8z4I+W3XaeDjjornA7cI=; b=R+SKBlKeo7xbHbBT6090verWLRm90LWEtao0ziWy9RX2SmVMf5Q+dAFN7u9WVRDwL6 +TvRtGT0VlVxUpYx9RDDCyRXTHADgpVcOI5sMYahHnpREPPdkqMCeKhZSY8vhSlki/jn YevDilN4fmNt1db6kGftCtqgN/iQu16Ck2PqM35IS/EE1Is/z/jWTPOo6SRJJjJ14fDf MLFhv0m1Tjw4JJlcg7CxVWScZu1XYx2sWcec41H0hbKTGoHERtAcO2zR/5+3Ovim9fg+ DS+SgEOGjgwwZuLf/cSEwEIXzJJKweiCzsfhil/sR0JsS9ItTM1ZQ25cy2Ip8syJAr8c tH4A== X-Gm-Message-State: AOJu0Yw+l7wPqkem+QbFqX2daB9ozTYFQDhoJsXPwtvvi55WD8RlaQE9 ALob2k4EZryzN7nemaWk54y8fPKxNrK9tANkkMZiauT/JxyJmFBSiu1C X-Gm-Gg: ASbGnctO4X7SEzLbbkvVveHkjRgbqShEu717dOZegZWeVPtvfd1uqE4D4jKxWMQi5uU yJXiyd1V4OSqcyvpixpuydeuGTzmRdCvTwMkj37MHW9SKois6oXOIq8jwZHzkKSGhz/yv4tdeib kLQxHzOQEw1ej6YQnghafPGMM3hcxVcgcJKS4dlpnHDKyG6dN96UipgYxr4x3Rm15TOVbfqHho8 FLOEbBCmEdIwVCANsqSuSB/hm9wri8v31COa4Is9aW9+RnuCyuU/hHL7ObDvOSkonhQEbZl4Owy pe9SAxipKEeibQuKEA4y3l3r4AQJNOGwNQMLRP5P94Zn7WBo1ZwR03Fcbhe/unL8Lz+r+baZzIx EPwDTVxsuGlzCNvm6kMidLBo6W7Ux0zFEwd7vQhRD8DUoB0Ev6D8QSu3hXKyVYzs8M45Lm5vEw5 nEvRJIToczSvi+ X-Google-Smtp-Source: AGHT+IET9QryomkBikFQhng7V6z/wthaGi8YTDl9dkFqWo2ju7Up65d26HbgFAlytHdQ8InaHLQJcg== X-Received: by 2002:a05:6602:6411:b0:893:6497:6042 with SMTP id ca18e2360f4ac-89d3336f2e0mr538966739f.16.1758135646457; Wed, 17 Sep 2025 12:00:46 -0700 (PDT) Received: from nathan (162-195-168-172.lightspeed.stlsmo.sbcglobal.net. [162.195.168.172]) by smtp.gmail.com with ESMTPSA id ca18e2360f4ac-8a4561d4886sm12508139f.0.2025.09.17.12.00.45 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 17 Sep 2025 12:00:45 -0700 (PDT) Date: Wed, 17 Sep 2025 14:00:43 -0500 From: Nathan Bossart To: Sami Imseih Cc: pgsql-hackers Subject: Re: GetNamedLWLockTranche crashes on Windows in normal backend Message-ID: References: MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="GHdcEctuM0LBkFpY" Content-Disposition: inline In-Reply-To: List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk --GHdcEctuM0LBkFpY Content-Type: text/plain; charset=us-ascii Content-Disposition: inline On Wed, Sep 17, 2025 at 11:43:31AM -0500, Sami Imseih wrote: > Thanks! v8 LGTM. Actually, we do want to have a few more startup tranches in order to get some coverage on the repalloc() path in RequestNamedLWLockTranche(). I've bumped it up to 32 and added a commit message to the patch. Barring more feedback, I'm planning to commit this soon. -- nathan --GHdcEctuM0LBkFpY Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0001-Add-a-test-harness-for-the-LWLock-tranche-code.patch From 112dc6f722daaaf3c08c8a268d19f6678a2d1cbe Mon Sep 17 00:00:00 2001 From: Nathan Bossart Date: Wed, 17 Sep 2025 13:45:49 -0500 Subject: [PATCH v9 1/1] Add a test harness for the LWLock tranche code. This code is heavily used and already has decent test coverage, but it lacks a dedicated test suite. This commit changes that. Author: Sami Imseih Co-authored-by: Nathan Bossart Reviewed-by: Bertrand Drouvot Discussion: https://postgr.es/m/CAA5RZ0tQ%2BEYSTOd2hQ8RXdsNfGBLAtOe-YmnsTE6ZVg0E-4qew%40mail.gmail.com Discussion: https://postgr.es/m/CAA5RZ0vpr0P2rbA%3D_K0_SCHM7bmfVX4wEO9FAyopN1eWCYORhA%40mail.gmail.com --- src/test/modules/Makefile | 1 + src/test/modules/meson.build | 1 + .../modules/test_lwlock_tranches/.gitignore | 4 + .../modules/test_lwlock_tranches/Makefile | 25 ++++ .../expected/test_lwlock_tranches.out | 32 +++++ .../modules/test_lwlock_tranches/meson.build | 35 ++++++ .../sql/test_lwlock_tranches.sql | 15 +++ .../test_lwlock_tranches--1.0.sql | 16 +++ .../test_lwlock_tranches.c | 110 ++++++++++++++++++ .../test_lwlock_tranches.conf | 1 + .../test_lwlock_tranches.control | 4 + 11 files changed, 244 insertions(+) create mode 100644 src/test/modules/test_lwlock_tranches/.gitignore create mode 100644 src/test/modules/test_lwlock_tranches/Makefile create mode 100644 src/test/modules/test_lwlock_tranches/expected/test_lwlock_tranches.out create mode 100644 src/test/modules/test_lwlock_tranches/meson.build create mode 100644 src/test/modules/test_lwlock_tranches/sql/test_lwlock_tranches.sql create mode 100644 src/test/modules/test_lwlock_tranches/test_lwlock_tranches--1.0.sql create mode 100644 src/test/modules/test_lwlock_tranches/test_lwlock_tranches.c create mode 100644 src/test/modules/test_lwlock_tranches/test_lwlock_tranches.conf create mode 100644 src/test/modules/test_lwlock_tranches/test_lwlock_tranches.control diff --git a/src/test/modules/Makefile b/src/test/modules/Makefile index 903a8ac151a..8a3cd2afab7 100644 --- a/src/test/modules/Makefile +++ b/src/test/modules/Makefile @@ -29,6 +29,7 @@ SUBDIRS = \ test_integerset \ test_json_parser \ test_lfind \ + test_lwlock_tranches \ test_misc \ test_oat_hooks \ test_parser \ diff --git a/src/test/modules/meson.build b/src/test/modules/meson.build index 93be0f57289..717e85066ba 100644 --- a/src/test/modules/meson.build +++ b/src/test/modules/meson.build @@ -28,6 +28,7 @@ subdir('test_int128') subdir('test_integerset') subdir('test_json_parser') subdir('test_lfind') +subdir('test_lwlock_tranches') subdir('test_misc') subdir('test_oat_hooks') subdir('test_parser') diff --git a/src/test/modules/test_lwlock_tranches/.gitignore b/src/test/modules/test_lwlock_tranches/.gitignore new file mode 100644 index 00000000000..5dcb3ff9723 --- /dev/null +++ b/src/test/modules/test_lwlock_tranches/.gitignore @@ -0,0 +1,4 @@ +# Generated subdirectories +/log/ +/results/ +/tmp_check/ diff --git a/src/test/modules/test_lwlock_tranches/Makefile b/src/test/modules/test_lwlock_tranches/Makefile new file mode 100644 index 00000000000..e357b7d6d66 --- /dev/null +++ b/src/test/modules/test_lwlock_tranches/Makefile @@ -0,0 +1,25 @@ +# src/test/modules/test_lwlock_tranches/Makefile + +MODULE_big = test_lwlock_tranches +OBJS = \ + $(WIN32RES) \ + test_lwlock_tranches.o +PGFILEDESC = "test_lwlock_tranches - test code for LWLock tranches allocated by extensions" + +EXTENSION = test_lwlock_tranches +DATA = test_lwlock_tranches--1.0.sql + +REGRESS_OPTS = --temp-config $(top_srcdir)/src/test/modules/test_lwlock_tranches/test_lwlock_tranches.conf +REGRESS = test_lwlock_tranches +NO_INSTALLCHECK = 1 + +ifdef USE_PGXS +PG_CONFIG = pg_config +PGXS := $(shell $(PG_CONFIG) --pgxs) +include $(PGXS) +else +subdir = src/test/modules/test_lwlock_tranches +top_builddir = ../../../.. +include $(top_builddir)/src/Makefile.global +include $(top_srcdir)/contrib/contrib-global.mk +endif diff --git a/src/test/modules/test_lwlock_tranches/expected/test_lwlock_tranches.out b/src/test/modules/test_lwlock_tranches/expected/test_lwlock_tranches.out new file mode 100644 index 00000000000..38c227b5bc3 --- /dev/null +++ b/src/test/modules/test_lwlock_tranches/expected/test_lwlock_tranches.out @@ -0,0 +1,32 @@ +CREATE EXTENSION test_lwlock_tranches; +\c +SELECT test_lwlock_tranches(); + test_lwlock_tranches +---------------------- + +(1 row) + +\c +SELECT test_lwlock_tranche_creation(NULL); +ERROR: tranche name cannot be NULL +\c +SELECT test_lwlock_tranche_creation(repeat('a', 64)); +ERROR: tranche name too long +DETAIL: LWLock tranche names must be no longer than 63 bytes. +\c +SELECT test_lwlock_tranche_creation('test'); +ERROR: maximum number of tranches already registered +DETAIL: No more than 256 tranches may be registered. +\c +SELECT test_lwlock_tranche_lookup('test_lwlock_tranches_startup'); + test_lwlock_tranche_lookup +---------------------------- + +(1 row) + +\c +SELECT test_lwlock_tranche_lookup('bogus'); +ERROR: requested tranche is not registered +\c +SELECT test_lwlock_initialize(65535); +ERROR: tranche 65535 is not registered diff --git a/src/test/modules/test_lwlock_tranches/meson.build b/src/test/modules/test_lwlock_tranches/meson.build new file mode 100644 index 00000000000..755c2b72267 --- /dev/null +++ b/src/test/modules/test_lwlock_tranches/meson.build @@ -0,0 +1,35 @@ +# Copyright (c) 2025, PostgreSQL Global Development Group + +test_lwlock_tranches_sources = files( + 'test_lwlock_tranches.c', +) + +if host_system == 'windows' + test_lwlock_tranches_sources += rc_lib_gen.process(win32ver_rc, extra_args: [ + '--NAME', 'test_lwlock_tranches', + '--FILEDESC', 'test_lwlock_tranches - test code for LWLock tranches allocated by extensions',]) +endif + +test_lwlock_tranches = shared_module('test_lwlock_tranches', + test_lwlock_tranches_sources, + kwargs: pg_test_mod_args, +) +test_install_libs += test_lwlock_tranches + +test_install_data += files( + 'test_lwlock_tranches.control', + 'test_lwlock_tranches--1.0.sql', +) + +tests += { + 'name': 'test_lwlock_tranches', + 'sd': meson.current_source_dir(), + 'bd': meson.current_build_dir(), + 'regress': { + 'sql': [ + 'test_lwlock_tranches', + ], + 'regress_args': ['--temp-config', files('test_lwlock_tranches.conf')], + 'runningcheck': false, + }, +} diff --git a/src/test/modules/test_lwlock_tranches/sql/test_lwlock_tranches.sql b/src/test/modules/test_lwlock_tranches/sql/test_lwlock_tranches.sql new file mode 100644 index 00000000000..18845343ebc --- /dev/null +++ b/src/test/modules/test_lwlock_tranches/sql/test_lwlock_tranches.sql @@ -0,0 +1,15 @@ +CREATE EXTENSION test_lwlock_tranches; +\c +SELECT test_lwlock_tranches(); +\c +SELECT test_lwlock_tranche_creation(NULL); +\c +SELECT test_lwlock_tranche_creation(repeat('a', 64)); +\c +SELECT test_lwlock_tranche_creation('test'); +\c +SELECT test_lwlock_tranche_lookup('test_lwlock_tranches_startup'); +\c +SELECT test_lwlock_tranche_lookup('bogus'); +\c +SELECT test_lwlock_initialize(65535); diff --git a/src/test/modules/test_lwlock_tranches/test_lwlock_tranches--1.0.sql b/src/test/modules/test_lwlock_tranches/test_lwlock_tranches--1.0.sql new file mode 100644 index 00000000000..34821981521 --- /dev/null +++ b/src/test/modules/test_lwlock_tranches/test_lwlock_tranches--1.0.sql @@ -0,0 +1,16 @@ +/* src/test/modules/test_lwlock_tranches/test_lwlock_tranches--1.0.sql */ + +-- complain if script is sourced in psql, rather than via CREATE EXTENSION +\echo Use "CREATE EXTENSION test_lwlock_tranches" to load this file. \quit + +CREATE FUNCTION test_lwlock_tranches() RETURNS VOID + AS 'MODULE_PATHNAME' LANGUAGE C; + +CREATE FUNCTION test_lwlock_tranche_creation(tranche_name TEXT) RETURNS VOID + AS 'MODULE_PATHNAME' LANGUAGE C; + +CREATE FUNCTION test_lwlock_tranche_lookup(tranche_name TEXT) RETURNS VOID + AS 'MODULE_PATHNAME' LANGUAGE C; + +CREATE FUNCTION test_lwlock_initialize(tranche_id INT) RETURNS VOID + AS 'MODULE_PATHNAME' LANGUAGE C; diff --git a/src/test/modules/test_lwlock_tranches/test_lwlock_tranches.c b/src/test/modules/test_lwlock_tranches/test_lwlock_tranches.c new file mode 100644 index 00000000000..4f6e3a8c007 --- /dev/null +++ b/src/test/modules/test_lwlock_tranches/test_lwlock_tranches.c @@ -0,0 +1,110 @@ +/*-------------------------------------------------------------------------- + * + * test_lwlock_tranches.c + * Test code for LWLock tranches allocated by extensions. + * + * Copyright (c) 2025, PostgreSQL Global Development Group + * + * IDENTIFICATION + * src/test/modules/test_lwlock_tranches/test_lwlock_tranches.c + * + * ------------------------------------------------------------------------- + */ + +#include "postgres.h" + +#include "fmgr.h" +#include "miscadmin.h" +#include "storage/lwlock.h" +#include "utils/builtins.h" +#include "utils/wait_classes.h" + +PG_MODULE_MAGIC; + +#define STARTUP_TRANCHE_NAME "test_lwlock_tranches_startup" +#define DYNAMIC_TRANCHE_NAME "test_lwlock_tranches_dynamic" + +#define NUM_STARTUP_TRANCHES (32) +#define NUM_DYNAMIC_TRANCHES (256 - NUM_STARTUP_TRANCHES) + +#define GET_TRANCHE_NAME(a) GetLWLockIdentifier(PG_WAIT_LWLOCK, (a)) + +static shmem_request_hook_type prev_shmem_request_hook; +static void test_lwlock_tranches_shmem_request(void); + +void +_PG_init(void) +{ + prev_shmem_request_hook = shmem_request_hook; + shmem_request_hook = test_lwlock_tranches_shmem_request; +} + +static void +test_lwlock_tranches_shmem_request(void) +{ + if (prev_shmem_request_hook) + prev_shmem_request_hook(); + + for (int i = 0; i < NUM_STARTUP_TRANCHES; i++) + RequestNamedLWLockTranche(STARTUP_TRANCHE_NAME, 1); +} + +PG_FUNCTION_INFO_V1(test_lwlock_tranches); +Datum +test_lwlock_tranches(PG_FUNCTION_ARGS) +{ + int dynamic_tranches[NUM_DYNAMIC_TRANCHES]; + + for (int i = 0; i < NUM_DYNAMIC_TRANCHES; i++) + dynamic_tranches[i] = LWLockNewTrancheId(DYNAMIC_TRANCHE_NAME); + + for (int i = 0; i < NUM_STARTUP_TRANCHES; i++) + { + if (strcmp(GET_TRANCHE_NAME(LWTRANCHE_FIRST_USER_DEFINED + i), + STARTUP_TRANCHE_NAME) != 0) + elog(ERROR, "incorrect startup lock tranche name"); + } + + for (int i = 0; i < NUM_DYNAMIC_TRANCHES; i++) + { + if (strcmp(GET_TRANCHE_NAME(dynamic_tranches[i]), + DYNAMIC_TRANCHE_NAME) != 0) + elog(ERROR, "incorrect dynamic lock tranche name"); + } + + PG_RETURN_VOID(); +} + +PG_FUNCTION_INFO_V1(test_lwlock_tranche_creation); +Datum +test_lwlock_tranche_creation(PG_FUNCTION_ARGS) +{ + char *tranche_name = PG_ARGISNULL(0) ? NULL : TextDatumGetCString(PG_GETARG_DATUM(0)); + + (void) LWLockNewTrancheId(tranche_name); + + PG_RETURN_VOID(); +} + +PG_FUNCTION_INFO_V1(test_lwlock_tranche_lookup); +Datum +test_lwlock_tranche_lookup(PG_FUNCTION_ARGS) +{ + char *tranche_name = TextDatumGetCString(PG_GETARG_DATUM(0)); + + (void) GetNamedLWLockTranche(tranche_name); + + PG_RETURN_VOID(); +} + +PG_FUNCTION_INFO_V1(test_lwlock_initialize); +Datum +test_lwlock_initialize(PG_FUNCTION_ARGS) +{ + int tranche_id = PG_GETARG_INT32(0); + LWLock lock; + + LWLockInitialize(&lock, tranche_id); + + PG_RETURN_VOID(); +} diff --git a/src/test/modules/test_lwlock_tranches/test_lwlock_tranches.conf b/src/test/modules/test_lwlock_tranches/test_lwlock_tranches.conf new file mode 100644 index 00000000000..acbe5bf51c3 --- /dev/null +++ b/src/test/modules/test_lwlock_tranches/test_lwlock_tranches.conf @@ -0,0 +1 @@ +shared_preload_libraries = 'test_lwlock_tranches' diff --git a/src/test/modules/test_lwlock_tranches/test_lwlock_tranches.control b/src/test/modules/test_lwlock_tranches/test_lwlock_tranches.control new file mode 100644 index 00000000000..1cde04bdc0b --- /dev/null +++ b/src/test/modules/test_lwlock_tranches/test_lwlock_tranches.control @@ -0,0 +1,4 @@ +comment = 'Test code for LWLock tranches allocated by extensions' +default_version = '1.0' +module_pathname = '$libdir/test_lwlock_tranches' +relocatable = true -- 2.39.5 (Apple Git-154) --GHdcEctuM0LBkFpY--