From b259ece92a951e799d8ace7a865d6269cc1cdd71 Mon Sep 17 00:00:00 2001 From: Heikki Linnakangas Date: Wed, 26 Aug 2026 12:59:18 +0300 Subject: [PATCH] Fix registering shmem callbacks in single-user mode RegisterShmemCallbacks() should not be called from the postmaster process after postmaster startup. Add an assertion for that, and fix the check for whether it's being called for "after startup" allocations to take single-user mode into account. Author: Ayush Tiwari Discussion: https://www.postgresql.org/message-id/CAJTYsWU7epjUL1-xrpYeOrmkmq20M2Q22Y_SRb8PWQG8KNQyDw@mail.gmail.com Backpatch-through: 19 --- src/backend/storage/ipc/shmem.c | 10 +++++++-- .../test_shmem/t/001_late_shmem_alloc.pl | 22 +++++++++++++++++++ 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/src/backend/storage/ipc/shmem.c b/src/backend/storage/ipc/shmem.c index 1fbba9c3a4c..85401f7bff6 100644 --- a/src/backend/storage/ipc/shmem.c +++ b/src/backend/storage/ipc/shmem.c @@ -872,23 +872,29 @@ ShmemAddrIsValid(const void *addr) void RegisterShmemCallbacks(const ShmemCallbacks *callbacks) { - if (shmem_request_state == SRS_DONE && IsUnderPostmaster) + if (shmem_request_state == SRS_DONE) { /* * After-startup initialization or attachment. Call the appropriate * callbacks immediately. + * + * This is not allowed from the postmaster, because the postmaster + * cannot acquire locks. */ if ((callbacks->flags & SHMEM_CALLBACKS_ALLOW_AFTER_STARTUP) == 0) elog(ERROR, "cannot request shared memory at this time"); + Assert(IsUnderPostmaster || !IsPostmasterEnvironment); CallShmemCallbacksAfterStartup(callbacks); } - else + else if (shmem_request_state == SRS_INITIAL) { /* Remember the callbacks for later */ registered_shmem_callbacks = lappend(registered_shmem_callbacks, (void *) callbacks); } + else + elog(ERROR, "cannot request shared memory at this time"); } /* 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 5cf07d071ec..546d6a92abe 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 @@ -27,6 +27,28 @@ cmp_ok($attach_count2, '>', $attach_count1, "attach callback is called in each backend"); $node->stop; +### +# Test allocating memory after startup in single-user mode +### +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 + if $windows_os; + 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); + + ok($result, "shmem area is initialized in single-user mode"); +} + ### # Test that loading via shared_preload_libraries also works ###