/****************************************************************************/
  /* IpcMemoryDetach(status, shmaddr)    removes a shared memory segment     */
 -/*                                     from process' address spaceq        */
 +/*                                     from process' address space         */
  /* (called as an on_shmem_exit callback, hence funny argument list)        */
  /****************************************************************************/
  static void
   /*
   * PGSharedMemoryReAttach
   *
 - * Re-attach to an already existing shared memory segment.  In the non
 - * EXEC_BACKEND case this is not used, because postmaster children inherit
 - * the shared memory segment attachment via fork().
 + * This is called during startup of a postmaster child process to re-attach to
 + * an already existing shared memory segment.  This is needed only in the
 + * EXEC_BACKEND case; otherwise postmaster children inherit the shared memory
 + * segment attachment via fork().
   *
   * UsedShmemSegID and UsedShmemSegAddr are implicit parameters to this
   * routine.  The caller must have already restored them to the postmaster's
   
     UsedShmemSegAddr = hdr;     /* probably redundant */
  }
 +
 +/*
 + * PGSharedMemoryNoReAttach
 + *
 + * This is called during startup of a postmaster child process when we choose
 + * *not* to re-attach to the existing shared memory segment.  We must clean up
 + * to leave things in the appropriate state.  This is not used in the non
 + * EXEC_BACKEND case, either.
 + *
 + * The child process startup logic might or might not call PGSharedMemoryDetach
 + * after this; make sure that it will be a no-op if called.
 + *
 + * UsedShmemSegID and UsedShmemSegAddr are implicit parameters to this
 + * routine.  The caller must have already restored them to the postmaster's
 + * values.
 + */
 +void
 +PGSharedMemoryNoReAttach(void)
 +{
 +   Assert(UsedShmemSegAddr != NULL);
 +   Assert(IsUnderPostmaster);
 +
 +#ifdef __CYGWIN__
 +   /* cygipc (currently) appears to not detach on exec. */
 +   PGSharedMemoryDetach();
 +#endif
 +
 +   /* For cleanliness, reset UsedShmemSegAddr to show we're not attached. */
 +   UsedShmemSegAddr = NULL;
 +   /* And the same for UsedShmemSegID. */
 +   UsedShmemSegID = 0;
 +}
 +
  #endif   /* EXEC_BACKEND */
  
  /*
   * PGSharedMemoryDetach
   *
   * Detach from the shared memory segment, if still attached.  This is not
 - * intended for use by the process that originally created the segment
 - * (it will have an on_shmem_exit callback registered to do that).  Rather,
 - * this is for subprocesses that have inherited an attachment and want to
 - * get rid of it.
 + * intended to be called explicitly by the process that originally created the
 + * segment (it will have an on_shmem_exit callback registered to do that).
 + * Rather, this is for subprocesses that have inherited an attachment and want
 + * to get rid of it.
 + *
 + * UsedShmemSegID and UsedShmemSegAddr are implicit parameters to this
 + * routine.
   */
  void
  PGSharedMemoryDetach(void)
          #include "storage/ipc.h"
  #include "storage/pg_shmem.h"
  
 -HANDLE     UsedShmemSegID = 0;
 +HANDLE     UsedShmemSegID = INVALID_HANDLE_VALUE;
  void      *UsedShmemSegAddr = NULL;
  static Size UsedShmemSegSize = 0;
  
    * we only care about shmem segments that are associated with the intended
   * DataDir.  This is an important consideration since accidental matches of
   * shmem segment IDs are reasonably common.
 - *
   */
  bool
  PGSharedMemoryIsInUse(unsigned long id1, unsigned long id2)
    * or recycle any existing segment. On win32, we always create a new segment,
   * since there is no need for recycling (segments go away automatically
   * when the last backend exits)
 - *
   */
  PGShmemHeader *
  PGSharedMemoryCreate(Size size, bool makePrivate, int port,
          elog(LOG, "could not close handle to shared memory: error code %lu", GetLastError());
  
  
 -   /* Register on-exit routine to delete the new segment */
 -   on_shmem_exit(pgwin32_SharedMemoryDelete, PointerGetDatum(hmap2));
 -
     /*
      * Get a pointer to the new shared memory segment. Map the whole segment
      * at once, and let the system decide on the initial address.
      UsedShmemSegSize = size;
     UsedShmemSegID = hmap2;
  
 +   /* Register on-exit routine to delete the new segment */
 +   on_shmem_exit(pgwin32_SharedMemoryDelete, PointerGetDatum(hmap2));
 +
     *shim = hdr;
     return hdr;
  }
   /*
   * PGSharedMemoryReAttach
   *
 - * Re-attach to an already existing shared memory segment. Use the
 - * handle inherited from the postmaster.
 + * This is called during startup of a postmaster child process to re-attach to
 + * an already existing shared memory segment, using the handle inherited from
 + * the postmaster.
   *
   * UsedShmemSegID and UsedShmemSegAddr are implicit parameters to this
   * routine.  The caller must have already restored them to the postmaster's
      UsedShmemSegAddr = hdr;     /* probably redundant */
  }
  
 +/*
 + * PGSharedMemoryNoReAttach
 + *
 + * This is called during startup of a postmaster child process when we choose
 + * *not* to re-attach to the existing shared memory segment.  We must clean up
 + * to leave things in the appropriate state.
 + *
 + * The child process startup logic might or might not call PGSharedMemoryDetach
 + * after this; make sure that it will be a no-op if called.
 + *
 + * UsedShmemSegID and UsedShmemSegAddr are implicit parameters to this
 + * routine.  The caller must have already restored them to the postmaster's
 + * values.
 + */
 +void
 +PGSharedMemoryNoReAttach(void)
 +{
 +   Assert(UsedShmemSegAddr != NULL);
 +   Assert(IsUnderPostmaster);
 +
 +   /*
 +    * Under Windows we will not have mapped the segment, so we don't need to
 +    * un-map it.  Just reset UsedShmemSegAddr to show we're not attached.
 +    */
 +   UsedShmemSegAddr = NULL;
 +
 +   /*
 +    * We *must* close the inherited shmem segment handle, else Windows will
 +    * consider the existence of this process to mean it can't release the
 +    * shmem segment yet.  We can now use PGSharedMemoryDetach to do that.
 +    */
 +   PGSharedMemoryDetach();
 +}
 +
  /*
   * PGSharedMemoryDetach
   *
   * Detach from the shared memory segment, if still attached.  This is not
 - * intended for use by the process that originally created the segment. Rather,
 - * this is for subprocesses that have inherited an attachment and want to
 - * get rid of it.
 + * intended to be called explicitly by the process that originally created the
 + * segment (it will have an on_shmem_exit callback registered to do that).
 + * Rather, this is for subprocesses that have inherited an attachment and want
 + * to get rid of it.
 + *
 + * UsedShmemSegID and UsedShmemSegAddr are implicit parameters to this
 + * routine.
   */
  void
  PGSharedMemoryDetach(void)
  {
 +   /* Unmap the view, if it's mapped */
     if (UsedShmemSegAddr != NULL)
     {
         if (!UnmapViewOfFile(UsedShmemSegAddr))
 -           elog(LOG, "could not unmap view of shared memory: error code %lu", GetLastError());
 +           elog(LOG, "could not unmap view of shared memory: error code %lu",
 +                GetLastError());
  
         UsedShmemSegAddr = NULL;
     }
 +
 +   /* And close the shmem handle, if we have one */
 +   if (UsedShmemSegID != INVALID_HANDLE_VALUE)
 +   {
 +       if (!CloseHandle(UsedShmemSegID))
 +           elog(LOG, "could not close handle to shared memory: error code %lu",
 +                GetLastError());
 +
 +       UsedShmemSegID = INVALID_HANDLE_VALUE;
 +   }
  }
  
  
  /*
 - * pgwin32_SharedMemoryDelete(status, shmId)       deletes a shared memory segment
 - * (called as an on_shmem_exit callback, hence funny argument list)
 + * pgwin32_SharedMemoryDelete
 + *
 + * Detach from and delete the shared memory segment
 + * (called as an on_shmem_exit callback, hence funny argument list)
   */
  static void
  pgwin32_SharedMemoryDelete(int status, Datum shmId)
  {
 +   Assert(DatumGetPointer(shmId) == UsedShmemSegID);
     PGSharedMemoryDetach();
 -   if (!CloseHandle(DatumGetPointer(shmId)))
 -       elog(LOG, "could not close handle to shared memory: error code %lu", GetLastError());
  }
  
  /*