From ce07aff48f15a2fa4f91bc67efe1cb3cc9c14bcf Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Mon, 30 Apr 2018 16:19:51 -0400
Subject: [PATCH] Further effort at preventing memory map dump from affecting
 the results.

Rather than elog'ing immediately, push the map data into a preallocated
StringInfo.  Perhaps this will prevent some of the mid-operation
allocations that are evidently happening now.

Discussion: https://postgr.es/m/25495.1524517820@sss.pgh.pa.us
---
 src/backend/port/win32_shmem.c | 34 +++++++++++++++++++++++-----------
 1 file changed, 23 insertions(+), 11 deletions(-)

diff --git a/src/backend/port/win32_shmem.c b/src/backend/port/win32_shmem.c
index 9e42665ed62..dd66756b991 100644
--- a/src/backend/port/win32_shmem.c
+++ b/src/backend/port/win32_shmem.c
@@ -12,6 +12,7 @@
  */
 #include "postgres.h"
 
+#include "lib/stringinfo.h"
 #include "miscadmin.h"
 #include "storage/dsm.h"
 #include "storage/ipc.h"
@@ -54,13 +55,17 @@ mi_state(DWORD code)
 	return "???";
 }
 
+/*
+ * Append memory dump to buf.  To avoid affecting the memory map mid-run,
+ * buf should be preallocated to be bigger than needed.
+ */
 static void
-dumpmem(const char *reason)
+dumpmem(StringInfo buf, const char *reason)
 {
 	char	   *addr = 0;
 	MEMORY_BASIC_INFORMATION mi;
 
-	elog(LOG, "%s memory map", reason);
+	appendStringInfo(buf, "%s memory map:", reason);
 	do
 	{
 		memset(&mi, 0, sizeof(mi));
@@ -68,12 +73,13 @@ dumpmem(const char *reason)
 		{
 			if (GetLastError() == ERROR_INVALID_PARAMETER)
 				break;
-			elog(LOG, "VirtualQuery failed: %lu", GetLastError());
+			appendStringInfo(buf, "\nVirtualQuery 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));
+		appendStringInfo(buf, "\n0x%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);
 }
@@ -442,11 +448,16 @@ PGSharedMemoryReAttach(void)
 {
 	PGShmemHeader *hdr;
 	void	   *origUsedShmemSegAddr = UsedShmemSegAddr;
+	StringInfoData buf;
 
 	Assert(UsedShmemSegAddr != NULL);
 	Assert(IsUnderPostmaster);
 
-	dumpmem("before VirtualFree");
+	/* Ensure buf is big enough that it won't grow mid-operation */
+	initStringInfo(&buf);
+	enlargeStringInfo(&buf, 128 * 1024);
+
+	dumpmem(&buf, "before VirtualFree");
 
 	/*
 	 * Release memory region reservation that was made by the postmaster
@@ -455,20 +466,19 @@ PGSharedMemoryReAttach(void)
 		elog(FATAL, "failed to release reserved memory region (addr=%p): error code %lu",
 			 UsedShmemSegAddr, GetLastError());
 
-	dumpmem("after VirtualFree");
+	dumpmem(&buf, "after VirtualFree");
 
 	hdr = (PGShmemHeader *) MapViewOfFileEx(UsedShmemSegID, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0, UsedShmemSegAddr);
 	if (!hdr)
 	{
 		DWORD		maperr = GetLastError();
 
-		dumpmem("after failed MapViewOfFileEx");
+		dumpmem(&buf, "after failed MapViewOfFileEx");
+		elog(LOG, "%s", buf.data);
 
 		elog(FATAL, "could not reattach to shared memory (key=%p, addr=%p): error code %lu",
 			 UsedShmemSegID, UsedShmemSegAddr, maperr);
 	}
-	else
-		dumpmem("after MapViewOfFileEx");
 	if (hdr != origUsedShmemSegAddr)
 		elog(FATAL, "reattaching to shared memory returned unexpected address (got %p, expected %p)",
 			 hdr, origUsedShmemSegAddr);
@@ -476,6 +486,8 @@ PGSharedMemoryReAttach(void)
 		elog(FATAL, "reattaching to shared memory returned non-PostgreSQL memory");
 	dsm_set_control_handle(hdr->dsm_control);
 
+	pfree(buf.data);
+
 	UsedShmemSegAddr = hdr;		/* probably redundant */
 }
 
-- 
GitLab