]> granicus.if.org Git - postgresql/commitdiff
Get still more info about Windows can't-reattach-to-shared-memory errors.
authorTom Lane <tgl@sss.pgh.pa.us>
Mon, 30 Apr 2018 00:41:19 +0000 (20:41 -0400)
committerTom Lane <tgl@sss.pgh.pa.us>
Mon, 30 Apr 2018 00:41:19 +0000 (20:41 -0400)
After some thought about the info captured so far, it seems possible
that MapViewOfFileEx is itself causing some DLL to get loaded into
the space just freed by VirtualFree.  The previous commit here didn't
capture enough info to really prove the case for that, so let's add
one more VirtualQuery in between those steps.  Also, be sure to
capture the post-Map state before we emit any log entries, just in
case elog() is invoking some code not previously loaded.

Discussion: https://postgr.es/m/25495.1524517820@sss.pgh.pa.us

src/backend/port/win32_shmem.c

index e724b3ef1a3231a632c6f0cf72f77579e92046c5..fe9cf3d1d6f9a573ddbd97cea26a76488cf9f26c 100644 (file)
@@ -389,16 +389,18 @@ PGSharedMemoryReAttach(void)
        PGShmemHeader *hdr;
        void       *origUsedShmemSegAddr = UsedShmemSegAddr;
        MEMORY_BASIC_INFORMATION previnfo;
-       DWORD           queryerr;
+       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)
-               queryerr = 0;
+               preverr = 0;
        else
-               queryerr = GetLastError();
+               preverr = GetLastError();
 
        /*
         * Release memory region reservation that was made by the postmaster
@@ -407,27 +409,48 @@ 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();
+
        hdr = (PGShmemHeader *) MapViewOfFileEx(UsedShmemSegID, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0, UsedShmemSegAddr);
        if (!hdr)
        {
                DWORD           maperr = GetLastError();
-               MEMORY_BASIC_INFORMATION info;
+               MEMORY_BASIC_INFORMATION postinfo;
+               DWORD           posterr;
+
+               /* Capture post-failure state */
+               if (VirtualQuery(UsedShmemSegAddr, &postinfo, sizeof(postinfo)) != 0)
+                       posterr = 0;
+               else
+                       posterr = GetLastError();
 
-               if (queryerr == 0)
+               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, queryerr);
+                                UsedShmemSegAddr, preverr);
 
-               if (VirtualQuery(UsedShmemSegAddr, &info, sizeof(info)) != 0)
+               if (aftererr == 0)
                        elog(LOG, "VirtualQuery(%p) after free reports region of size %zu, base %p, has state 0x%lx",
-                                UsedShmemSegAddr, info.RegionSize,
-                                info.AllocationBase, info.State);
+                                UsedShmemSegAddr, afterinfo.RegionSize,
+                                afterinfo.AllocationBase, afterinfo.State);
                else
                        elog(LOG, "VirtualQuery(%p) after free failed: error code %lu",
-                                UsedShmemSegAddr, GetLastError());
+                                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);
 
                elog(FATAL, "could not reattach to shared memory (key=%p, addr=%p): error code %lu",
                         UsedShmemSegID, UsedShmemSegAddr, maperr);