summaryrefslogtreecommitdiff
path: root/src/backend/port/win32_shmem.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2018-04-30 11:16:21 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2018-04-30 11:16:21 -0400
commit6ba0cc4bd3a6d738eddf7e8aa2ef7b46cdd9ce8f (patch)
tree697bdbd1984a055c0f4a13fbb2b683a4308ac6d8 /src/backend/port/win32_shmem.c
parentc5e46c7c3b9333616de9946f8e63df1576a19800 (diff)
Dump full memory maps around failing Windows reattach code.
This morning's results from buildfarm member dory make it pretty clear that something is getting mapped into the just-freed space, but not what that something is. Replace my minimalistic probes with a full dump of the process address space and module space, based on Noah's work at <20170403065106.GA2624300%40tornado.leadboat.com> This is all (probably) to get reverted once we have fixed the problem, but for now we need information. Discussion: https://postgr.es/m/25495.1524517820@sss.pgh.pa.us
Diffstat (limited to 'src/backend/port/win32_shmem.c')
-rw-r--r--src/backend/port/win32_shmem.c134
1 files changed, 89 insertions, 45 deletions
diff --git a/src/backend/port/win32_shmem.c b/src/backend/port/win32_shmem.c
index fe9cf3d1d6f..7402052ce61 100644
--- a/src/backend/port/win32_shmem.c
+++ b/src/backend/port/win32_shmem.c
@@ -12,6 +12,8 @@
*/
#include "postgres.h"
+#include <psapi.h>
+
#include "miscadmin.h"
#include "storage/dsm.h"
#include "storage/ipc.h"
@@ -24,6 +26,88 @@ static Size UsedShmemSegSize = 0;
static bool EnableLockPagesPrivilege(int elevel);
static void pgwin32_SharedMemoryDelete(int status, Datum shmId);
+/* Dump all modules loaded into proc */
+static void
+dumpdlls(HANDLE proc)
+{
+ HMODULE dll[1024];
+ DWORD size_used = 1;
+ int i,
+ n;
+
+ if (!EnumProcessModules(proc, dll, sizeof(dll), &size_used))
+ {
+ elog(LOG, "EnumProcessModules failed: %lu", GetLastError());
+ return;
+ }
+ n = (int) (size_used / sizeof(*dll));
+ elog(LOG, "EnumProcessModules: %d modules in process 0x%p", n, proc);
+ for (i = 0; i < n; i++)
+ {
+ char name[MAXPGPATH];
+
+ if (!GetModuleFileNameEx(proc, dll[i], name, sizeof(name)))
+ sprintf(name, "GetModuleFileNameEx failed: %lu", GetLastError());
+ elog(LOG, "%d: 0x%p %s", i + 1, dll[i], name);
+ }
+}
+
+static const char *
+mi_type(DWORD code)
+{
+ switch (code)
+ {
+ case MEM_IMAGE:
+ return "img";
+ case MEM_MAPPED:
+ return "map";
+ case MEM_PRIVATE:
+ return "prv";
+ }
+ return "???";
+}
+
+static const char *
+mi_state(DWORD code)
+{
+ switch (code)
+ {
+ case MEM_COMMIT:
+ return "commit";
+ case MEM_FREE:
+ return "free ";
+ case MEM_RESERVE:
+ return "reserv";
+ }
+ return "???";
+}
+
+static void
+dumpmem(const char *reason, HANDLE proc)
+{
+ char *addr = 0;
+ MEMORY_BASIC_INFORMATION mi;
+
+ elog(LOG, "%s memory map", reason);
+ do
+ {
+ memset(&mi, 0, sizeof(mi));
+ if (!VirtualQueryEx(proc, addr, &mi, sizeof(mi)))
+ {
+ if (GetLastError() == ERROR_INVALID_PARAMETER)
+ break;
+ elog(LOG, "VirtualQueryEx failed: %lu", GetLastError());
+ break;
+ }
+ elog(LOG, "0x%p+0x%p %s (alloc 0x%p) %s",
+ mi.BaseAddress, (void *) mi.RegionSize,
+ mi_type(mi.Type), mi.AllocationBase, mi_state(mi.State));
+ addr += mi.RegionSize;
+ } while (addr > 0);
+
+ dumpdlls(proc);
+}
+
/*
* Generate shared memory segment name. Expand the data directory, to generate
* an identifier unique for this data directory. Then replace all backslashes
@@ -388,19 +472,11 @@ PGSharedMemoryReAttach(void)
{
PGShmemHeader *hdr;
void *origUsedShmemSegAddr = UsedShmemSegAddr;
- MEMORY_BASIC_INFORMATION previnfo;
- MEMORY_BASIC_INFORMATION afterinfo;
- DWORD preverr;
- DWORD aftererr;
Assert(UsedShmemSegAddr != NULL);
Assert(IsUnderPostmaster);
- /* Preliminary probe of region we intend to release */
- if (VirtualQuery(UsedShmemSegAddr, &previnfo, sizeof(previnfo)) != 0)
- preverr = 0;
- else
- preverr = GetLastError();
+ dumpmem("before VirtualFree", GetCurrentProcess());
/*
* Release memory region reservation that was made by the postmaster
@@ -409,48 +485,14 @@ PGSharedMemoryReAttach(void)
elog(FATAL, "failed to release reserved memory region (addr=%p): error code %lu",
UsedShmemSegAddr, GetLastError());
- /* Verify post-release state */
- if (VirtualQuery(UsedShmemSegAddr, &afterinfo, sizeof(afterinfo)) != 0)
- aftererr = 0;
- else
- aftererr = GetLastError();
+ dumpmem("after VirtualFree", GetCurrentProcess());
hdr = (PGShmemHeader *) MapViewOfFileEx(UsedShmemSegID, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0, UsedShmemSegAddr);
if (!hdr)
{
DWORD maperr = GetLastError();
- MEMORY_BASIC_INFORMATION postinfo;
- DWORD posterr;
-
- /* Capture post-failure state */
- if (VirtualQuery(UsedShmemSegAddr, &postinfo, sizeof(postinfo)) != 0)
- posterr = 0;
- else
- posterr = GetLastError();
-
- if (preverr == 0)
- elog(LOG, "VirtualQuery(%p) before free reports region of size %zu, base %p, has state 0x%lx",
- UsedShmemSegAddr, previnfo.RegionSize,
- previnfo.AllocationBase, previnfo.State);
- else
- elog(LOG, "VirtualQuery(%p) before free failed: error code %lu",
- UsedShmemSegAddr, preverr);
- if (aftererr == 0)
- elog(LOG, "VirtualQuery(%p) after free reports region of size %zu, base %p, has state 0x%lx",
- UsedShmemSegAddr, afterinfo.RegionSize,
- afterinfo.AllocationBase, afterinfo.State);
- else
- elog(LOG, "VirtualQuery(%p) after free failed: error code %lu",
- UsedShmemSegAddr, aftererr);
-
- if (posterr == 0)
- elog(LOG, "VirtualQuery(%p) after map reports region of size %zu, base %p, has state 0x%lx",
- UsedShmemSegAddr, postinfo.RegionSize,
- postinfo.AllocationBase, postinfo.State);
- else
- elog(LOG, "VirtualQuery(%p) after map failed: error code %lu",
- UsedShmemSegAddr, posterr);
+ dumpmem("after MapViewOfFileEx", GetCurrentProcess());
elog(FATAL, "could not reattach to shared memory (key=%p, addr=%p): error code %lu",
UsedShmemSegID, UsedShmemSegAddr, maperr);
@@ -597,5 +639,7 @@ pgwin32_ReserveSharedMemoryRegion(HANDLE hChild)
return false;
}
+ dumpmem("after reserve", hChild);
+
return true;
}