postgres.git / summary / log / commit / refs

commit    6ba0cc4bd3a6d738eddf7e8aa2ef7b46cdd9ce8f
Author:   Tom Lane <tgl@sss.pgh.pa.us>
Date:     Mon Apr 30 15:16:21 2018 +0000
First released in: master (reverted before release)
Reverted by: bcbf2346d69f (in 11.0)

    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


src/backend/Makefile | 2 +- src/backend/port/win32_shmem.c | 134 +++++++++++++++++++++++++++-------------- src/makefiles/Makefile.win32 | 2 + src/tools/msvc/Mkvcbuild.pm | 2 + 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'); [parent: c5e46c7c3b93]