Re: [PATCH] "could not reattach to shared memory" on Windows - Mailing list pgsql-hackers

From Tsutomu Yamada
Subject Re: [PATCH] "could not reattach to shared memory" on Windows
Date
Msg-id 64677.1247649630@srapc2360.sra.co.jp
Whole thread Raw
In response to [PATCH] "could not reattach to shared memory" on Windows  (Tsutomu Yamada <tsutomu@sraoss.co.jp>)
Responses Re: [PATCH] "could not reattach to shared memory" on Windows
List pgsql-hackers
Hello,

Alvaro Herrera <alvherre@commandprompt.com> wrote:
 > Tsutomu Yamada wrote:
 >
 > > This patch using VirtualAlloc()/VirtualFree() to avoid failing in
 > > reattach to shared memory.
 > >
 > > Can this be added to CommitFest ?
 >
 > Since this fixes a very annoying bug present in older versions, I think
 > this should be backpatched all the way back to 8.2.
 >
 > Some notes about the patch itself:
 >
 > - please use ereport() instead of elog() for error messages
 > - Are you really putting the pgwin32_ReserveSharedMemory declaration
 > inside a function?  Please move that into the appropriate header file.
 > - Failure to reserve memory in pgwin32_ReserveSharedMemory should be a
 > FATAL error I think, not simply LOG.

In this case,
the parent process operates child's memory by using VirtualAlloc().
If VirtualAlloc failed and be a FATAL error, master process will be stopped.

I think that is not preferable.
So, when VirtualAlloc failed, parent reports error and terminates child.

Revised patch

- move function declaration to include/port/win32.h
- add error check.
  when VirtualAlloc failed, parent will terminate child process.

Thanks.

--
Tsutomu Yamada
SRA OSS, Inc. Japan

Index: src/backend/port/win32_shmem.c
===================================================================
RCS file: /mnt/prj/pg/cvsmirror/pg/pgsql/src/backend/port/win32_shmem.c,v
retrieving revision 1.11
diff -c -r1.11 win32_shmem.c
*** src/backend/port/win32_shmem.c    11 Jun 2009 14:49:00 -0000    1.11
--- src/backend/port/win32_shmem.c    15 Jul 2009 08:56:34 -0000
***************
*** 18,23 ****
--- 18,24 ----

  unsigned long UsedShmemSegID = 0;
  void       *UsedShmemSegAddr = NULL;
+ static Size UsedShmemSegSize = 0;

  static void pgwin32_SharedMemoryDelete(int status, Datum shmId);

***************
*** 233,238 ****
--- 234,240 ----

      /* Save info for possible future use */
      UsedShmemSegAddr = memAddress;
+     UsedShmemSegSize = size;
      UsedShmemSegID = (unsigned long) hmap2;

      return hdr;
***************
*** 257,262 ****
--- 259,273 ----
      Assert(UsedShmemSegAddr != NULL);
      Assert(IsUnderPostmaster);

+     /* release memory region
+      * that reserved by parant process
+      */
+     if (VirtualFree(UsedShmemSegAddr, 0, MEM_RELEASE) == 0)
+     {
+         elog(LOG, "failed to release reserved memory region (addr=%p): %lu",
+              UsedShmemSegAddr, GetLastError());
+     }
+
      hdr = (PGShmemHeader *) MapViewOfFileEx((HANDLE) UsedShmemSegID, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0,
UsedShmemSegAddr);
      if (!hdr)
          elog(FATAL, "could not reattach to shared memory (key=%d, addr=%p): %lu",
***************
*** 302,304 ****
--- 313,337 ----
      if (!CloseHandle((HANDLE) DatumGetInt32(shmId)))
          elog(LOG, "could not close handle to shared memory: %lu", GetLastError());
  }
+
+ /*
+  * pgwin32_ReserveSharedMemory(HANDLE pChild)
+  * Reserve shared memory area,
+  * BEFORE child process allocates memory for DLL and/or others.
+  */
+ int
+ pgwin32_ReserveSharedMemory(HANDLE pChild)
+ {
+     void *memAddress;
+
+     Assert(UsedShmemSegAddr != NULL);
+     Assert(UsedShmemSegSize != 0);
+     memAddress = VirtualAllocEx(pChild, UsedShmemSegAddr, UsedShmemSegSize,
+                                 MEM_RESERVE, PAGE_READWRITE);
+     if (memAddress == NULL) {
+         elog(LOG, "could not reserve shared memory region (addr=%p): %lu",
+              UsedShmemSegAddr, GetLastError());
+         return false;
+     }
+     return true;
+ }
Index: src/backend/postmaster/postmaster.c
===================================================================
RCS file: /mnt/prj/pg/cvsmirror/pg/pgsql/src/backend/postmaster/postmaster.c,v
retrieving revision 1.584
diff -c -r1.584 postmaster.c
*** src/backend/postmaster/postmaster.c    8 Jul 2009 18:55:35 -0000    1.584
--- src/backend/postmaster/postmaster.c    15 Jul 2009 07:37:09 -0000
***************
*** 3643,3648 ****
--- 3643,3660 ----
          elog(LOG, "could not close handle to backend parameter file: error code %d",
               (int) GetLastError());

+     /* reserve shared memory area before ResumeThread() */
+     if (!pgwin32_ReserveSharedMemory(pi.hProcess))
+     {
+         if (!TerminateProcess(pi.hProcess, 255))
+             ereport(ERROR,
+                     (errmsg_internal("could not terminate process that failed to reserve memory: error code %d",
+                                      (int) GetLastError())));
+         CloseHandle(pi.hProcess);
+         CloseHandle(pi.hThread);
+         return -1;            /* elog() made by pgwin32_ReserveSharedMemory() */
+     }
+
      /*
       * Now that the backend variables are written out, we start the child
       * thread so it can start initializing while we set up the rest of the
Index: src/include/port/win32.h
===================================================================
RCS file: /mnt/prj/pg/cvsmirror/pg/pgsql/src/include/port/win32.h,v
retrieving revision 1.88
diff -c -r1.88 win32.h
*** src/include/port/win32.h    11 Jun 2009 14:49:12 -0000    1.88
--- src/include/port/win32.h    15 Jul 2009 08:39:23 -0000
***************
*** 288,293 ****
--- 288,296 ----
  extern int    pgwin32_is_service(void);
  #endif

+ /* in backend/port/win32_shmem.c */
+ extern int    pgwin32_ReserveSharedMemory(HANDLE);
+
  /* in port/win32error.c */
  extern void _dosmaperr(unsigned long);


pgsql-hackers by date:

Previous
From: Andrea Suisani
Date:
Subject: Re: Mysql.whynot or PG vs MySQL comparison table?
Next
From: Peter Eisentraut
Date:
Subject: Re: navigation menu for documents