Commit 6ba0cc4b authored by Tom Lane's avatar Tom Lane

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
parent c5e46c7c
......@@ -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)
......
......@@ -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;
}
# src/makefiles/Makefile.win32
override CPPFLAGS+= -DPSAPI_VERSION=1
ifdef PGXS
BE_DLLLIBS= -L$(libdir) -lpostgres
override CPPFLAGS+= -I$(includedir_server)/port/win32
......
......@@ -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');
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment