From 5e7a5c9511b65d483639dd3f7dfab7b9e92c3433 Mon Sep 17 00:00:00 2001
From: Bruce Momjian <bruce@momjian.us>
Date: Thu, 8 May 2003 14:49:04 +0000
Subject: [PATCH] Pass shared memory address on command line to exec'ed
 backend.

Allow backends to attached to specified shared memory address.
---
 src/backend/bootstrap/bootstrap.c   |  9 ++-
 src/backend/port/sysv_shmem.c       | 89 ++++++++++++++++++-----------
 src/backend/postmaster/postmaster.c | 12 ++--
 src/backend/tcop/postgres.c         | 12 ++--
 src/include/storage/pg_shmem.h      |  3 +-
 5 files changed, 78 insertions(+), 47 deletions(-)

diff --git a/src/backend/bootstrap/bootstrap.c b/src/backend/bootstrap/bootstrap.c
index 215e165cf72..54b541a0d6c 100644
--- a/src/backend/bootstrap/bootstrap.c
+++ b/src/backend/bootstrap/bootstrap.c
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/bootstrap/bootstrap.c,v 1.155 2003/05/06 23:34:55 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/bootstrap/bootstrap.c,v 1.156 2003/05/08 14:49:03 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -286,10 +286,13 @@ BootstrapMain(int argc, char *argv[])
 			case 'p':
 			{
 				/* indicates fork from postmaster */
-				char *p;
 #ifdef EXEC_BACKEND
-				sscanf(optarg, "%d,", &UsedShmemSegID);
+				char *p;
+
+				sscanf(optarg, "%d,%p,", &UsedShmemSegID, &UsedShmemSegAddr);
 				p = strchr(optarg, ',');
+				if (p)
+					p = strchr(p+1, ',');
 				if (p)
 					dbname = strdup(p+1);
 #else
diff --git a/src/backend/port/sysv_shmem.c b/src/backend/port/sysv_shmem.c
index c98aff5231e..9454c3e92cc 100644
--- a/src/backend/port/sysv_shmem.c
+++ b/src/backend/port/sysv_shmem.c
@@ -10,7 +10,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/port/sysv_shmem.c,v 1.8 2003/05/06 23:34:55 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/port/sysv_shmem.c,v 1.9 2003/05/08 14:49:03 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -39,9 +39,8 @@ typedef int IpcMemoryId;		/* shared memory ID returned by shmget(2) */
 #define IPCProtection	(0600)	/* access/modify by user only */
 
 
-#ifdef EXEC_BACKEND
 IpcMemoryKey UsedShmemSegID = 0;
-#endif
+void *UsedShmemSegAddr = NULL;
 
 static void *InternalIpcMemoryCreate(IpcMemoryKey memKey, uint32 size);
 static void IpcMemoryDetach(int status, Datum shmaddr);
@@ -282,7 +281,7 @@ PrivateMemoryDelete(int status, Datum memaddr)
  *
  * Create a shared memory segment of the given size and initialize its
  * standard header.  Also, register an on_shmem_exit callback to release
- * the storage.
+ * the storage.  For an exec'ed backend, it just attaches.
  *
  * Dead Postgres segments are recycled if found, but we do not fail upon
  * collision with non-Postgres shmem segments.	The idea here is to detect and
@@ -302,11 +301,9 @@ PGSharedMemoryCreate(uint32 size, bool makePrivate, int port)
 	/* Room for a header? */
 	Assert(size > MAXALIGN(sizeof(PGShmemHeader)));
 
-#ifdef EXEC_BACKEND
-	if (UsedShmemSegID != 0)
+	if (ExecBackend && UsedShmemSegID != 0)
 		NextShmemSegID = UsedShmemSegID;
 	else
-#endif
 		NextShmemSegID = port * 1000 + 1;
 
 	for (;;NextShmemSegID++)
@@ -320,25 +317,39 @@ PGSharedMemoryCreate(uint32 size, bool makePrivate, int port)
 			break;
 		}
 
-		/* Try to create new segment */
-		memAddress = InternalIpcMemoryCreate(NextShmemSegID, size);
-		if (memAddress)
-			break;				/* successful create and attach */
+		/* 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 */
 
-#if defined(solaris) && defined(__sparc__)
 		/* use intimate shared memory on SPARC Solaris */
-		memAddress = shmat(shmid, 0, SHM_SHARE_MMU);
+		memAddress = shmat(shmid, UsedShmemSegAddr,
+#if defined(solaris) && defined(__sparc__)
+				SHM_SHARE_MMU
 #else
-		memAddress = shmat(shmid, 0, 0);
+				0
 #endif
+			);
 
 		if (memAddress == (void *) -1)
 			continue;			/* failed: must be some other app's */
+
 		hdr = (PGShmemHeader *) memAddress;
 		if (hdr->magic != PGShmemMagic)
 		{
@@ -346,14 +357,19 @@ PGSharedMemoryCreate(uint32 size, bool makePrivate, int port)
 			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 the creator PID is my own PID or does not belong to any
-		 * extant process, it's safe to zap it.
+		 * If I am not the creator and it belongs to an extant process,
+		 * continue.
 		 */
 		if (hdr->creatorPID != getpid())
 		{
-			if (kill(hdr->creatorPID, 0) == 0 ||
-				errno != ESRCH)
+			if (kill(hdr->creatorPID, 0) == 0 || errno != ESRCH)
 			{
 				shmdt(memAddress);
 				continue;		/* segment belongs to a live process */
@@ -385,26 +401,31 @@ PGSharedMemoryCreate(uint32 size, bool makePrivate, int port)
 		 */
 	}
 
-	/*
-	 * 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 || 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));
+	}
 
-#ifdef EXEC_BACKEND
-	if (!makePrivate && UsedShmemSegID == 0)
+	if (ExecBackend && !makePrivate && UsedShmemSegAddr == NULL)
+	{
+		UsedShmemSegAddr = memAddress;
 		UsedShmemSegID = NextShmemSegID;
-#endif
+	}
 
 	return hdr;
 }
diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index 23c948ce2ba..211fc216f9c 100644
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -37,7 +37,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.322 2003/05/06 23:34:55 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.323 2003/05/08 14:49:03 momjian Exp $
  *
  * NOTES
  *
@@ -2439,9 +2439,10 @@ BackendFinalize(Port *port)
 	 */
 	av[ac++] = "-p";
 #ifdef EXEC_BACKEND
-	Assert(UsedShmemSegID != 0);
+ 	Assert(UsedShmemSegID != 0 && UsedShmemSegAddr != NULL);
 	/* database name at the end because it might contain commas */
-	snprintf(pbuf, NAMEDATALEN + 256, "%d,%d,%s", port->sock, UsedShmemSegID, port->database_name);
+	snprintf(pbuf, NAMEDATALEN + 256, "%d,%d,%p,%s", port->sock,
+					UsedShmemSegID, UsedShmemSegAddr, port->database_name);
 	av[ac++] = pbuf;
 #else
 	av[ac++] = port->database_name;
@@ -2776,9 +2777,10 @@ SSDataBase(int xlop)
 
 		av[ac++] = "-p";
 #ifdef EXEC_BACKEND
-		Assert(UsedShmemSegID != 0);
+	 	Assert(UsedShmemSegID != 0 && UsedShmemSegAddr != NULL);
 		/* database name at the end because it might contain commas */
-		snprintf(pbuf, NAMEDATALEN + 256, "%d,%s", UsedShmemSegID, "template1");
+		snprintf(pbuf, NAMEDATALEN + 256, "%d,%p,%s", UsedShmemSegID,
+						UsedShmemSegAddr, "template1");
 		av[ac++] = pbuf;
 #else
 		av[ac++] = "template1";
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 78696cd0771..89564558708 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.338 2003/05/06 23:34:55 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.339 2003/05/08 14:49:04 momjian Exp $
  *
  * NOTES
  *	  this is the "main" module of the postgres backend and
@@ -2025,13 +2025,17 @@ PostgresMain(int argc, char *argv[], const char *username)
 				 */
 				if (secure)
 				{
-					char *p;
 #ifdef EXEC_BACKEND
-					sscanf(optarg, "%d,%d,", &MyProcPort->sock, &UsedShmemSegID);
+					char *p;
+
+					sscanf(optarg, "%d,%d,%p,", &MyProcPort->sock,
+									&UsedShmemSegID, &UsedShmemSegAddr);
 					/* Grab dbname as last param */
 					p = strchr(optarg, ',');
 					if (p)
 						p = strchr(p+1, ',');
+					if (p)					
+						p = strchr(p+1, ',');
 					if (p)					
 						dbname = strdup(p+1);
 #else
@@ -2393,7 +2397,7 @@ PostgresMain(int argc, char *argv[], const char *username)
 	if (!IsUnderPostmaster)
 	{
 		puts("\nPOSTGRES backend interactive interface ");
-		puts("$Revision: 1.338 $ $Date: 2003/05/06 23:34:55 $\n");
+		puts("$Revision: 1.339 $ $Date: 2003/05/08 14:49:04 $\n");
 	}
 
 	/*
diff --git a/src/include/storage/pg_shmem.h b/src/include/storage/pg_shmem.h
index 5f9df7602a1..0c2b9cb299d 100644
--- a/src/include/storage/pg_shmem.h
+++ b/src/include/storage/pg_shmem.h
@@ -17,7 +17,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: pg_shmem.h,v 1.5 2003/05/06 23:34:56 momjian Exp $
+ * $Id: pg_shmem.h,v 1.6 2003/05/08 14:49:04 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -38,6 +38,7 @@ typedef struct PGShmemHeader	/* standard header for all Postgres shmem */
 
 #ifdef EXEC_BACKEND
 extern IpcMemoryKey UsedShmemSegID;
+extern void *UsedShmemSegAddr;
 #endif
 
 extern PGShmemHeader *PGSharedMemoryCreate(uint32 size, bool makePrivate,
-- 
GitLab