From 753e07739b4e0e906e87f24e15e2c217de28f17d Mon Sep 17 00:00:00 2001 From: Andreas Karlsson Date: Thu, 4 Jun 2026 13:54:22 +0200 Subject: [PATCH v2 2/3] valgrind: Add NOACCESS sentinels to allocations in main shared memory When built with USE_VALGRIND we have the ShmemAllocator add a NOACCESS sentinel after every allocation in shared memory. On EXEC_BACKEND builds we set up the sentinels when the backend attaches to shared memory, but then only for things in ShmemIndex and not for allocations done directly via legacy functions like ShmemAlloc(). Author: Andreas Karlsson --- src/backend/storage/ipc/shmem.c | 38 ++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/src/backend/storage/ipc/shmem.c b/src/backend/storage/ipc/shmem.c index f1f7cd3a4ff..a7077be097b 100644 --- a/src/backend/storage/ipc/shmem.c +++ b/src/backend/storage/ipc/shmem.c @@ -142,6 +142,7 @@ #include "storage/shmem_internal.h" #include "storage/spin.h" #include "utils/builtins.h" +#include "utils/memdebug.h" #include "utils/tuplestore.h" /* @@ -279,6 +280,13 @@ static bool AttachShmemIndexEntry(ShmemRequest *request, bool missing_ok); Datum pg_numa_available(PG_FUNCTION_ARGS); +/* With valgrind, we want to add a couple NOACCESS bytes */ +#ifdef USE_VALGRIND +#define NOACCESS_BYTES 32 +#else +#define NOACCESS_BYTES 0 +#endif + /* * ShmemRequestStruct() --- request a named shared memory area * @@ -405,9 +413,14 @@ ShmemGetRequestedSize(void) /* pad the start address for alignment like ShmemAllocRaw() does */ if (alignment < PG_CACHE_LINE_SIZE) alignment = PG_CACHE_LINE_SIZE; + size = TYPEALIGN(alignment, size); size = add_size(size, request->options->size); + +#if USE_VALGRIND + size = add_size(size, NOACCESS_BYTES); +#endif } return size; @@ -492,6 +505,26 @@ ShmemAttachRequested(void) callbacks->attach_fn(callbacks->opaque_arg); } +#ifdef USE_VALGRIND + { + HASH_SEQ_STATUS hstat; + ShmemIndexEnt *ent; + + hash_seq_init(&hstat, ShmemIndex); + + /* + * When compiled with EXEC_BACKEND we need to recreate all NOACCESS + * regions in each backend, but we can only recreate those with index + * entries and not any of the regions for memory allocated directly with + * ShmemAlloc(). + */ + while ((ent = (ShmemIndexEnt *) hash_seq_search(&hstat)) != NULL) + { + VALGRIND_MAKE_MEM_NOACCESS(ent->location + ent->size, NOACCESS_BYTES); + } + } +#endif + LWLockRelease(ShmemIndexLock); shmem_request_state = SRS_DONE; @@ -822,11 +855,14 @@ ShmemAllocRaw(Size size, Size alignment, Size *allocated_size) rawStart = ShmemAllocator->free_offset; newStart = TYPEALIGN(alignment, rawStart); - newFree = newStart + size; + newFree = newStart + size + NOACCESS_BYTES; if (newFree <= ShmemSegHdr->totalsize) { newSpace = (char *) ShmemBase + newStart; ShmemAllocator->free_offset = newFree; + + /* Make the bytes at the end no-access */ + VALGRIND_MAKE_MEM_NOACCESS(newSpace + size, NOACCESS_BYTES); } else newSpace = NULL; -- 2.43.0