From 6ded021b3b22a8ad205a81d3af7d987470fa95c8 Mon Sep 17 00:00:00 2001 From: Ayush Tiwari Date: Sun, 20 Sep 2026 00:29:44 +0530 Subject: [PATCH v1 1/2] Fix legacy shmem reattachment in single-user mode ShmemInitStruct() only looks for an existing allocation when IsUnderPostmaster is true. In a standalone backend, a second call for the same area instead attempts to initialize it again and errors out. This differs from the legacy API's behavior before the shared-memory registration refactor. Look up existing allocations regardless of process type, as the old implementation did. Add a test that checks reattachment returns the same pointer in normal and single-user backends. Backpatch-through: 19 --- src/backend/storage/ipc/shmem.c | 7 +----- .../test_shmem/t/001_late_shmem_alloc.pl | 23 +++++++++++-------- .../modules/test_shmem/test_shmem--1.0.sql | 4 ++++ src/test/modules/test_shmem/test_shmem.c | 16 +++++++++++++ 4 files changed, 35 insertions(+), 15 deletions(-) diff --git a/src/backend/storage/ipc/shmem.c b/src/backend/storage/ipc/shmem.c index 3345735dff0c5923b491d72c9440cafc1b265998..c0a8fb39e47a7ff773d0ac3740d34cdec2c03339 100644 --- a/src/backend/storage/ipc/shmem.c +++ b/src/backend/storage/ipc/shmem.c @@ -1131,12 +1131,7 @@ ShmemInitStruct(const char *name, Size size, bool *foundPtr) LWLockAcquire(ShmemIndexLock, LW_EXCLUSIVE); - /* - * During postmaster startup, look up the existing entry if any. - */ - *foundPtr = false; - if (IsUnderPostmaster) - *foundPtr = AttachShmemIndexEntry(&request, true); + *foundPtr = AttachShmemIndexEntry(&request, true); /* Initialize it if not found */ if (!*foundPtr) diff --git a/src/test/modules/test_shmem/t/001_late_shmem_alloc.pl b/src/test/modules/test_shmem/t/001_late_shmem_alloc.pl index 7d961fe279085581b4ebdc2c3a95a8e21b02383c..cd0077229484ee3a400da5d8d389ca9416b1616f 100644 --- a/src/test/modules/test_shmem/t/001_late_shmem_alloc.pl +++ b/src/test/modules/test_shmem/t/001_late_shmem_alloc.pl @@ -29,6 +29,9 @@ my $attach_count2 = cmp_ok($attach_count2, '>', $attach_count1, "attach callback is called in each backend"); +is($node->safe_psql("postgres", "SELECT test_shmem_legacy();"), 't', + "legacy shared memory allocation can attach to an existing area"); + $node->stop; ### @@ -55,19 +58,21 @@ SKIP: { # Skip the test on Windows, as single-user mode would fail on permission # failure with privileged accounts. - skip 'single-user test is not supported by this platform', 1 + skip 'single-user test is not supported by this platform', 2 if $windows_os; + my @command = ( + 'postgres', '--single', '-F', + '-c' => 'exit_on_error=true', + '-D' => $node->data_dir, + 'postgres'); my $query = "SELECT get_test_shmem_attach_count();\n"; - my $result = run_log( - [ - 'postgres', '--single', '-F', - '-c' => 'exit_on_error=true', - '-D' => $node->data_dir, - 'postgres' - ], - '<' => \$query); + my $result = run_log(\@command, '<' => \$query); ok($result, "shmem area is initialized in single-user mode"); + + $query = "SELECT test_shmem_legacy();\n"; + $result = run_log(\@command, '<' => \$query); + ok($result, "legacy shared memory reattachment works in single-user mode"); } ### diff --git a/src/test/modules/test_shmem/test_shmem--1.0.sql b/src/test/modules/test_shmem/test_shmem--1.0.sql index 2d01fd9256c1bd27b84bbd2d4c987ba20e8636ab..04ead79e3482465ad4c71e441f3b1043bca5f5a5 100644 --- a/src/test/modules/test_shmem/test_shmem--1.0.sql +++ b/src/test/modules/test_shmem/test_shmem--1.0.sql @@ -4,6 +4,10 @@ \echo Use "CREATE EXTENSION test_shmem" to load this file. \quit +CREATE FUNCTION test_shmem_legacy() +RETURNS pg_catalog.bool STRICT +AS 'MODULE_PATHNAME' LANGUAGE C; + CREATE FUNCTION get_test_shmem_attach_count() RETURNS pg_catalog.int4 STRICT AS 'MODULE_PATHNAME' LANGUAGE C; diff --git a/src/test/modules/test_shmem/test_shmem.c b/src/test/modules/test_shmem/test_shmem.c index 2a7e13512bfa21ddfb5d6047423d4e1bc4390d9d..d2f1e004886e2a0560450381a270fbcd579616b5 100644 --- a/src/test/modules/test_shmem/test_shmem.c +++ b/src/test/modules/test_shmem/test_shmem.c @@ -129,3 +129,19 @@ get_test_shmem_attach_count(PG_FUNCTION_ARGS) elog(ERROR, "shmem area not yet initialized"); PG_RETURN_INT32(TestShmem->attach_count); } + +PG_FUNCTION_INFO_V1(test_shmem_legacy); +Datum +test_shmem_legacy(PG_FUNCTION_ARGS) +{ + void *first; + void *second; + bool found; + + first = ShmemInitStruct("test_shmem legacy", 64, &found); + second = ShmemInitStruct("test_shmem legacy", 64, &found); + if (!found || first != second) + elog(ERROR, "could not reattach to legacy shared memory area"); + + PG_RETURN_BOOL(found); +} base-commit: e73841ffbceea314cf9fa3f64a5eae9f87a46449 -- 2.34.1