Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 6ba0cc4

Browse files
committed
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
1 parent c5e46c7 commit 6ba0cc4

File tree

4 files changed

+94
-46
lines changed

4 files changed

+94
-46
lines changed

src/backend/Makefile

+1-1
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ libpostgres.a: postgres
7979
endif # cygwin
8080

8181
ifeq ($(PORTNAME), win32)
82-
LIBS += -lsecur32
82+
LIBS += -lsecur32 -lpsapi
8383

8484
postgres: $(OBJS) $(WIN32RES)
8585
$(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)

src/backend/port/win32_shmem.c

+89-45
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
*/
1313
#include "postgres.h"
1414

15+
#include <psapi.h>
16+
1517
#include "miscadmin.h"
1618
#include "storage/dsm.h"
1719
#include "storage/ipc.h"
@@ -24,6 +26,88 @@ static Size UsedShmemSegSize = 0;
2426
static bool EnableLockPagesPrivilege(int elevel);
2527
static void pgwin32_SharedMemoryDelete(int status, Datum shmId);
2628

29+
/* Dump all modules loaded into proc */
30+
static void
31+
dumpdlls(HANDLE proc)
32+
{
33+
HMODULE dll[1024];
34+
DWORD size_used = 1;
35+
int i,
36+
n;
37+
38+
if (!EnumProcessModules(proc, dll, sizeof(dll), &size_used))
39+
{
40+
elog(LOG, "EnumProcessModules failed: %lu", GetLastError());
41+
return;
42+
}
43+
n = (int) (size_used / sizeof(*dll));
44+
elog(LOG, "EnumProcessModules: %d modules in process 0x%p", n, proc);
45+
for (i = 0; i < n; i++)
46+
{
47+
char name[MAXPGPATH];
48+
49+
if (!GetModuleFileNameEx(proc, dll[i], name, sizeof(name)))
50+
sprintf(name, "GetModuleFileNameEx failed: %lu", GetLastError());
51+
elog(LOG, "%d: 0x%p %s", i + 1, dll[i], name);
52+
}
53+
}
54+
55+
static const char *
56+
mi_type(DWORD code)
57+
{
58+
switch (code)
59+
{
60+
case MEM_IMAGE:
61+
return "img";
62+
case MEM_MAPPED:
63+
return "map";
64+
case MEM_PRIVATE:
65+
return "prv";
66+
}
67+
return "???";
68+
}
69+
70+
static const char *
71+
mi_state(DWORD code)
72+
{
73+
switch (code)
74+
{
75+
case MEM_COMMIT:
76+
return "commit";
77+
case MEM_FREE:
78+
return "free ";
79+
case MEM_RESERVE:
80+
return "reserv";
81+
}
82+
return "???";
83+
}
84+
85+
static void
86+
dumpmem(const char *reason, HANDLE proc)
87+
{
88+
char *addr = 0;
89+
MEMORY_BASIC_INFORMATION mi;
90+
91+
elog(LOG, "%s memory map", reason);
92+
do
93+
{
94+
memset(&mi, 0, sizeof(mi));
95+
if (!VirtualQueryEx(proc, addr, &mi, sizeof(mi)))
96+
{
97+
if (GetLastError() == ERROR_INVALID_PARAMETER)
98+
break;
99+
elog(LOG, "VirtualQueryEx failed: %lu", GetLastError());
100+
break;
101+
}
102+
elog(LOG, "0x%p+0x%p %s (alloc 0x%p) %s",
103+
mi.BaseAddress, (void *) mi.RegionSize,
104+
mi_type(mi.Type), mi.AllocationBase, mi_state(mi.State));
105+
addr += mi.RegionSize;
106+
} while (addr > 0);
107+
108+
dumpdlls(proc);
109+
}
110+
27111
/*
28112
* Generate shared memory segment name. Expand the data directory, to generate
29113
* an identifier unique for this data directory. Then replace all backslashes
@@ -388,19 +472,11 @@ PGSharedMemoryReAttach(void)
388472
{
389473
PGShmemHeader *hdr;
390474
void *origUsedShmemSegAddr = UsedShmemSegAddr;
391-
MEMORY_BASIC_INFORMATION previnfo;
392-
MEMORY_BASIC_INFORMATION afterinfo;
393-
DWORD preverr;
394-
DWORD aftererr;
395475

396476
Assert(UsedShmemSegAddr != NULL);
397477
Assert(IsUnderPostmaster);
398478

399-
/* Preliminary probe of region we intend to release */
400-
if (VirtualQuery(UsedShmemSegAddr, &previnfo, sizeof(previnfo)) != 0)
401-
preverr = 0;
402-
else
403-
preverr = GetLastError();
479+
dumpmem("before VirtualFree", GetCurrentProcess());
404480

405481
/*
406482
* Release memory region reservation that was made by the postmaster
@@ -409,48 +485,14 @@ PGSharedMemoryReAttach(void)
409485
elog(FATAL, "failed to release reserved memory region (addr=%p): error code %lu",
410486
UsedShmemSegAddr, GetLastError());
411487

412-
/* Verify post-release state */
413-
if (VirtualQuery(UsedShmemSegAddr, &afterinfo, sizeof(afterinfo)) != 0)
414-
aftererr = 0;
415-
else
416-
aftererr = GetLastError();
488+
dumpmem("after VirtualFree", GetCurrentProcess());
417489

418490
hdr = (PGShmemHeader *) MapViewOfFileEx(UsedShmemSegID, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0, UsedShmemSegAddr);
419491
if (!hdr)
420492
{
421493
DWORD maperr = GetLastError();
422-
MEMORY_BASIC_INFORMATION postinfo;
423-
DWORD posterr;
424-
425-
/* Capture post-failure state */
426-
if (VirtualQuery(UsedShmemSegAddr, &postinfo, sizeof(postinfo)) != 0)
427-
posterr = 0;
428-
else
429-
posterr = GetLastError();
430-
431-
if (preverr == 0)
432-
elog(LOG, "VirtualQuery(%p) before free reports region of size %zu, base %p, has state 0x%lx",
433-
UsedShmemSegAddr, previnfo.RegionSize,
434-
previnfo.AllocationBase, previnfo.State);
435-
else
436-
elog(LOG, "VirtualQuery(%p) before free failed: error code %lu",
437-
UsedShmemSegAddr, preverr);
438494

439-
if (aftererr == 0)
440-
elog(LOG, "VirtualQuery(%p) after free reports region of size %zu, base %p, has state 0x%lx",
441-
UsedShmemSegAddr, afterinfo.RegionSize,
442-
afterinfo.AllocationBase, afterinfo.State);
443-
else
444-
elog(LOG, "VirtualQuery(%p) after free failed: error code %lu",
445-
UsedShmemSegAddr, aftererr);
446-
447-
if (posterr == 0)
448-
elog(LOG, "VirtualQuery(%p) after map reports region of size %zu, base %p, has state 0x%lx",
449-
UsedShmemSegAddr, postinfo.RegionSize,
450-
postinfo.AllocationBase, postinfo.State);
451-
else
452-
elog(LOG, "VirtualQuery(%p) after map failed: error code %lu",
453-
UsedShmemSegAddr, posterr);
495+
dumpmem("after MapViewOfFileEx", GetCurrentProcess());
454496

455497
elog(FATAL, "could not reattach to shared memory (key=%p, addr=%p): error code %lu",
456498
UsedShmemSegID, UsedShmemSegAddr, maperr);
@@ -597,5 +639,7 @@ pgwin32_ReserveSharedMemoryRegion(HANDLE hChild)
597639
return false;
598640
}
599641

642+
dumpmem("after reserve", hChild);
643+
600644
return true;
601645
}

src/makefiles/Makefile.win32

+2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# src/makefiles/Makefile.win32
22

3+
override CPPFLAGS+= -DPSAPI_VERSION=1
4+
35
ifdef PGXS
46
BE_DLLLIBS= -L$(libdir) -lpostgres
57
override CPPFLAGS+= -I$(includedir_server)/port/win32

src/tools/msvc/Mkvcbuild.pm

+2
Original file line numberDiff line numberDiff line change
@@ -174,8 +174,10 @@ sub mkvcbuild
174174
'repl_gram.y', 'syncrep_scanner.l',
175175
'syncrep_gram.y');
176176
$postgres->AddDefine('BUILDING_DLL');
177+
$postgres->AddDefine('PSAPI_VERSION=1');
177178
$postgres->AddLibrary('secur32.lib');
178179
$postgres->AddLibrary('ws2_32.lib');
180+
$postgres->AddLibrary('psapi.lib');
179181
$postgres->AddLibrary('wldap32.lib') if ($solution->{options}->{ldap});
180182
$postgres->FullExportDLL('postgres.lib');
181183

0 commit comments

Comments
 (0)