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;
}