| From: | PG Bug reporting form <noreply(at)postgresql(dot)org> |
|---|---|
| To: | pgsql-bugs(at)lists(dot)postgresql(dot)org |
| Cc: | s-mitsufuji(at)nec(dot)com |
| Subject: | BUG #19719: BUG: huge_pages=on shared memory reattached without FILE_MAP_LARGE_PAGES on Windows |
| Date: | 2026-09-25 04:39:16 |
| Message-ID: | 19719-9eea21ac8841c776@postgresql.org |
| Views: | Whole Thread | Raw Message | Download mbox | Resend email |
| Thread: | |
| Lists: | pgsql-bugs |
The following bug has been logged on the website:
Bug reference: 19719
Logged by: Satoshi Mitsufuji
Email address: s-mitsufuji(at)nec(dot)com
PostgreSQL version: 18.6
Operating system: Windows 11
Description:
PostgreSQL version: 18.6 (also affects master and any branch since
large-page support for Windows shared memory was introduced)
OS: Windows 10/11 x86_64, msvc build
huge_pages = on
Description
-----------
On Windows, when huge_pages=on, PGSharedMemoryCreate() (win32_shmem.c)
correctly creates the shared memory section with SEC_LARGE_PAGES and
maps the postmaster's own view with FILE_MAP_LARGE_PAGES:
if ((flProtect & SEC_LARGE_PAGES) != 0)
desiredAccess |= FILE_MAP_LARGE_PAGES;
memAddress = MapViewOfFileEx(hmap2, desiredAccess, 0, 0, 0, NULL);
However, every other backend process re-attaches to the same section
via PGSharedMemoryReAttach(), which calls MapViewOfFileEx() with only
FILE_MAP_READ | FILE_MAP_WRITE -- FILE_MAP_LARGE_PAGES is never
requested there. As a result, only the postmaster's own view of shared
memory is backed by large pages; every backend, walsender, autovacuum
worker, etc. maps the same physical section as ordinary 4KB pages.
Because Windows requires FILE_MAP_LARGE_PAGES on MapViewOfFileEx when
the underlying section was created with SEC_LARGE_PAGES (mirroring the
requirement added for CreateFileMapping in commit fdd8937c, see also
bug #17448), this looks like an oversight in that same fix: the
postmaster side was updated, but PGSharedMemoryReAttach() was not.
Evidence
--------
Using Sysinternals VMMap on the shared memory VA range in both the
postmaster and a backend process (huge_pages=on, shared_buffers=256MB,
segment size 292,864 KB):
Postmaster view of the segment:
Total WS : 292,864 K (100% of the segment, resident immediately)
Locked : 292,864 K
Process Page Table size: ~244-276 K
Backend view of the *same* segment, before fix:
Total WS : 1,668 K (only touched pages faulted in)
Locked : (column not present -- not large-page backed)
Process Page Table size: ~840 K (comparable to a plain
huge_pages=off backend, ~816-840 K)
The backend's page table consumption and lazily-faulted working set
are indistinguishable from a huge_pages=off run, indicating the
backend is using standard 4KB PTEs for this mapping despite
huge_pages=on and despite the section itself being backed by large
pages.
RAMMap's "Large Page" counter does not reflect this at all (stays at
0 K in both configurations), which is presumably why this has not
been noticed via that tool; VMMap's per-VAD Locked/WS accounting is
what exposes it.
Proposed fix
------------
Request FILE_MAP_LARGE_PAGES in PGSharedMemoryReAttach() as well,
falling back to a plain mapping if the section was not created with
SEC_LARGE_PAGES (huge_pages=off, or huge_pages=try that fell back to
normal pages):
--- win32_shmem_originalg.c
+++ win32_shmem_modified_20260922.c
@@ -440,7 +440,17 @@
if (VirtualFree(UsedShmemSegAddr, 0, MEM_RELEASE) == 0)
elog(FATAL, "failed to release reserved memory region
(addr=%p): error code %lu",
UsedShmemSegAddr, GetLastError());
+#ifdef FILE_MAP_LARGE_PAGES
+ /*
+ * Try to reattach with FILE_MAP_LARGE_PAGES first. This will fail
with
+ * ERROR_INVALID_PARAMETER if the segment was not created with
+ * SEC_LARGE_PAGES (i.e. huge_pages was off, or fell back to normal
+ * pages under huge_pages=try). In that case, retry without the
flag.
+ */
+ hdr = (PGShmemHeader *) MapViewOfFileEx(UsedShmemSegID,
FILE_MAP_READ | FILE_MAP_WRITE | FILE_MAP_LARGE_PAGES, 0, 0, 0,
UsedShmemSegAddr);
+ if (!hdr)
+ hdr = (PGShmemHeader *) MapViewOfFileEx(UsedShmemSegID,
FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0, UsedShmemSegAddr);
+#else
hdr = (PGShmemHeader *) MapViewOfFileEx(UsedShmemSegID,
FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0, UsedShmemSegAddr);
+#endif
if (!hdr)
elog(FATAL, "could not reattach to shared memory (key=%p,
addr=%p): error code %lu",
UsedShmemSegID, UsedShmemSegAddr, GetLastError());
I've tested this patch with both huge_pages=on and huge_pages=off:
- huge_pages=off: server starts normally. The first
MapViewOfFileEx() attempt (with FILE_MAP_LARGE_PAGES) fails as
expected since the section has no SEC_LARGE_PAGES, and the
fallback call succeeds -- no FATAL errors, no crash loop.
- huge_pages=on: backends now show Total WS == segment size and
Locked == segment size for the shared memory VAD in VMMap,
matching the postmaster, instead of the partial/non-locked view
seen before the fix.
| From | Date | Subject | |
|---|---|---|---|
| Next Message | shihao zhong | 2026-09-25 04:59:59 | Re: BUG #19699: LIKE with a trailing escape fails to raise SQLSTATE 22025 for empty input |
| Previous Message | shihao zhong | 2026-09-25 04:37:21 | Re: BUG #19714: pgcrypto pgp_sym_encrypt accepts nonnumeric s2k-mode as mode 0 |