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