summaryrefslogtreecommitdiff
path: root/src
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
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')
-rw-r--r--src/backend/Makefile2
-rw-r--r--src/backend/port/win32_shmem.c134
-rw-r--r--src/makefiles/Makefile.win322
-rw-r--r--src/tools/msvc/Mkvcbuild.pm2
4 files changed, 94 insertions, 46 deletions
diff --git a/src/backend/Makefile b/src/backend/Makefile
index 1aaf1ec2f59..f9215cdbb50 100644
--- a/src/backend/Makefile
+++ b/src/backend/Makefile
@@ -79,7 +79,7 @@ libpostgres.a: postgres
endif # cygwin
ifeq ($(PORTNAME), win32)
-LIBS += -lsecur32
+LIBS += -lsecur32 -lpsapi
postgres: $(OBJS) $(WIN32RES)
$(CC) $(CFLAGS) $(LDFLAGS) $(LDFLAGS_EX) -Wl,--stack=$(WIN32_STACK_RLIMIT) -Wl,--export-all-symbols -Wl,--out-implib=libpostgres.a $(call expand_subsys,$(OBJS)) $(WIN32RES) $(LIBS) -o $@$(X)
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;
}
diff --git a/src/makefiles/Makefile.win32 b/src/makefiles/Makefile.win32
index 7abbd01971a..678371d5f2a 100644
--- a/src/makefiles/Makefile.win32
+++ b/src/makefiles/Makefile.win32
@@ -1,5 +1,7 @@
# src/makefiles/Makefile.win32
+override CPPFLAGS+= -DPSAPI_VERSION=1
+
ifdef PGXS
BE_DLLLIBS= -L$(libdir) -lpostgres
override CPPFLAGS+= -I$(includedir_server)/port/win32
diff --git a/src/tools/msvc/Mkvcbuild.pm b/src/tools/msvc/Mkvcbuild.pm
index b2f5fd61853..ceac0add4eb 100644
--- a/src/tools/msvc/Mkvcbuild.pm
+++ b/src/tools/msvc/Mkvcbuild.pm
@@ -174,8 +174,10 @@ sub mkvcbuild
'repl_gram.y', 'syncrep_scanner.l',
'syncrep_gram.y');
$postgres->AddDefine('BUILDING_DLL');
+ $postgres->AddDefine('PSAPI_VERSION=1');
$postgres->AddLibrary('secur32.lib');
$postgres->AddLibrary('ws2_32.lib');
+ $postgres->AddLibrary('psapi.lib');
$postgres->AddLibrary('wldap32.lib') if ($solution->{options}->{ldap});
$postgres->FullExportDLL('postgres.lib');