Cleanup of shared memory attach - Mailing list pgsql-patches

From Bruce Momjian
Subject Cleanup of shared memory attach
Date
Msg-id 200305081917.h48JHsX11686@candle.pha.pa.us
Whole thread Raw
List pgsql-patches
This patch moves attaching to shared memory out into a separate
function, for code clarity after exec() changes.

--
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 359-1001
  +  If your life is a hard drive,     |  13 Roberts Road
  +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073
Index: src/backend/port/sysv_shmem.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/backend/port/sysv_shmem.c,v
retrieving revision 1.9
diff -c -c -r1.9 sysv_shmem.c
*** src/backend/port/sysv_shmem.c    8 May 2003 14:49:03 -0000    1.9
--- src/backend/port/sysv_shmem.c    8 May 2003 19:00:12 -0000
***************
*** 47,52 ****
--- 47,54 ----
  static void IpcMemoryDelete(int status, Datum shmId);
  static void *PrivateMemoryCreate(uint32 size);
  static void PrivateMemoryDelete(int status, Datum memaddr);
+ static PGShmemHeader *PGSharedMemoryAttach(IpcMemoryKey key,
+                                         IpcMemoryId *shmid, void *addr);


  /*
***************
*** 297,368 ****
      IpcMemoryKey NextShmemSegID;
      void       *memAddress;
      PGShmemHeader *hdr;

      /* Room for a header? */
      Assert(size > MAXALIGN(sizeof(PGShmemHeader)));

!     if (ExecBackend && UsedShmemSegID != 0)
!         NextShmemSegID = UsedShmemSegID;
!     else
!         NextShmemSegID = port * 1000 + 1;
!
!     for (;;NextShmemSegID++)
      {
!         IpcMemoryId shmid;
!
!         /* Special case if creating a private segment --- just malloc() it */
!         if (makePrivate)
          {
!             memAddress = PrivateMemoryCreate(size);
!             break;
!         }
!
!         /* If attach to fixed address, only try once */
!         if (ExecBackend && UsedShmemSegAddr != NULL && NextShmemSegID != UsedShmemSegID)
!         {
!             fprintf(stderr, "Unable to attach to memory at fixed address: shmget(key=%d, addr=%p) failed: %s\n",
                  (int) UsedShmemSegID, UsedShmemSegAddr, strerror(errno));
              proc_exit(1);
          }

!         if (!ExecBackend || UsedShmemSegAddr == NULL)
!         {
!             /* Try to create new segment */
!             memAddress = InternalIpcMemoryCreate(NextShmemSegID, size);
!             if (memAddress)
!                 break;                /* successful create and attach */
!         }
!
!         /* See if it looks to be leftover from a dead Postgres process */
!         shmid = shmget(NextShmemSegID, sizeof(PGShmemHeader), 0);
!         if (shmid < 0)
!             continue;            /* failed: must be some other app's */
!
!         /* use intimate shared memory on SPARC Solaris */
!         memAddress = shmat(shmid, UsedShmemSegAddr,
! #if defined(solaris) && defined(__sparc__)
!                 SHM_SHARE_MMU
! #else
!                 0
! #endif
!             );
!
!         if (memAddress == (void *) -1)
!             continue;            /* failed: must be some other app's */

!         hdr = (PGShmemHeader *) memAddress;
!         if (hdr->magic != PGShmemMagic)
          {
!             shmdt(memAddress);
!             continue;            /* segment belongs to a non-Postgres app */
          }

!         /* Successfully attached to shared memory, which is all we wanted */
!         if (ExecBackend && UsedShmemSegAddr != NULL)
!             break;

          /* Check shared memory and possibly remove and recreate */

          /*
           * If I am not the creator and it belongs to an extant process,
           * continue.
--- 299,346 ----
      IpcMemoryKey NextShmemSegID;
      void       *memAddress;
      PGShmemHeader *hdr;
+     IpcMemoryId shmid;

      /* Room for a header? */
      Assert(size > MAXALIGN(sizeof(PGShmemHeader)));

!     /* Just attach and return the pointer */
!     if (ExecBackend && UsedShmemSegAddr != NULL && !makePrivate)
      {
!         if ((hdr = (PGShmemHeader *) memAddress = PGSharedMemoryAttach(
!                         UsedShmemSegID, &shmid, UsedShmemSegAddr)) == NULL)
          {
!             fprintf(stderr, "Unable to attach to proper memory at fixed address: shmget(key=%d, addr=%p) failed:
%s\n",
                  (int) UsedShmemSegID, UsedShmemSegAddr, strerror(errno));
              proc_exit(1);
          }
+         return hdr;
+     }

!     /* Create shared memory */
!
!     NextShmemSegID = port * 1000 + 1;

!     for (;;NextShmemSegID++)
!     {
!         /* Special case if creating a private segment --- just malloc() it */
!         if (makePrivate)
          {
!             memAddress = PrivateMemoryCreate(size);
!             break;
          }

!         /* Try to create new segment */
!         memAddress = InternalIpcMemoryCreate(NextShmemSegID, size);
!         if (memAddress)
!             break;                /* successful create and attach */

          /* Check shared memory and possibly remove and recreate */

+         if ((hdr = (PGShmemHeader *) memAddress = PGSharedMemoryAttach(
+                         NextShmemSegID, &shmid, UsedShmemSegAddr)) == NULL)
+             continue;            /* can't attach, not one of mine */
+
          /*
           * If I am not the creator and it belongs to an extant process,
           * continue.
***************
*** 401,431 ****
           */
      }

      hdr = (PGShmemHeader *) memAddress;

!     if (!ExecBackend || makePrivate || UsedShmemSegAddr == NULL)
!     {
!         /*
!          * OK, we created a new segment.  Mark it as created by this process.
!          * The order of assignments here is critical so that another Postgres
!          * process can't see the header as valid but belonging to an invalid
!          * PID!
!          */
!         hdr->creatorPID = getpid();
!         hdr->magic = PGShmemMagic;
!
!         /*
!          * Initialize space allocation status for segment.
!          */
!         hdr->totalsize = size;
!         hdr->freeoffset = MAXALIGN(sizeof(PGShmemHeader));
!     }

!     if (ExecBackend && !makePrivate && UsedShmemSegAddr == NULL)
      {
          UsedShmemSegAddr = memAddress;
          UsedShmemSegID = NextShmemSegID;
      }

      return hdr;
  }
--- 379,438 ----
           */
      }

+     /*
+      * OK, we created a new segment.  Mark it as created by this process.
+      * The order of assignments here is critical so that another Postgres
+      * process can't see the header as valid but belonging to an invalid
+      * PID!
+      */
      hdr = (PGShmemHeader *) memAddress;
+     hdr->creatorPID = getpid();
+     hdr->magic = PGShmemMagic;

!     /*
!      * Initialize space allocation status for segment.
!      */
!     hdr->totalsize = size;
!     hdr->freeoffset = MAXALIGN(sizeof(PGShmemHeader));

!
!     if (ExecBackend && UsedShmemSegAddr == NULL && !makePrivate)
      {
          UsedShmemSegAddr = memAddress;
          UsedShmemSegID = NextShmemSegID;
      }
+
+     return hdr;
+ }
+
+
+ /*
+  *    Attach to shared memory and make sure it has a Postgres header
+  */
+ static PGShmemHeader *
+ PGSharedMemoryAttach(IpcMemoryKey key, IpcMemoryId *shmid, void *addr)
+ {
+     PGShmemHeader *hdr;
+
+     if ((*shmid = shmget(key, sizeof(PGShmemHeader), 0)) < 0)
+         return NULL;

+     hdr = (PGShmemHeader *) shmat(*shmid, UsedShmemSegAddr,
+ #if defined(solaris) && defined(__sparc__)
+             /* use intimate shared memory on SPARC Solaris */
+             SHM_SHARE_MMU
+ #else
+             0
+ #endif
+         );
+
+     if (hdr == (PGShmemHeader *) -1)
+         return NULL;            /* failed: must be some other app's */
+
+     if (hdr->magic != PGShmemMagic)
+     {
+         shmdt(hdr);
+         return NULL;            /* segment belongs to a non-Postgres app */
+     }
      return hdr;
  }

pgsql-patches by date:

Previous
From: Tom Lane
Date:
Subject: Re: GUC patch for Win32
Next
From: Bruce Momjian
Date:
Subject: Re: GUC patch for Win32