postgres.git / summary / log / commit / refs

commit    a74740fbd3bb89cd626f6e98417847f696e60bd8
Author:   Tom Lane <tgl@sss.pgh.pa.us>
Date:     Sat Apr 15 21:27:38 2017 +0000

    Provide a way to control SysV shmem attach address in EXEC_BACKEND builds.
    
    In standard non-Windows builds, there's no particular reason to care what
    address the kernel chooses to map the shared memory segment at.  However,
    when building with EXEC_BACKEND, there's a risk that the chosen address
    won't be available in all child processes.  Linux with ASLR enabled (which
    it is by default) seems particularly at risk because it puts shmem segments
    into the same area where it maps shared libraries.  We can work around
    that by specifying a mapping address that's outside the range where
    shared libraries could get mapped.  On x86_64 Linux, 0x7e0000000000
    seems to work well.
    
    This is only meant for testing/debugging purposes, so it doesn't seem
    necessary to go as far as providing a GUC (or any user-visible
    documentation, though we might change that later).  Instead, it's just
    controlled by setting an environment variable PG_SHMEM_ADDR to the
    desired attach address.
    
    Back-patch to all supported branches, since the point here is to
    remove intermittent buildfarm failures on EXEC_BACKEND animals.
    Owners of affected animals will need to add a suitable setting of
    PG_SHMEM_ADDR to their build_env configuration.
    
    Discussion: https://postgr.es/m/7036.1492231361@sss.pgh.pa.us


src/backend/port/sysv_shmem.c | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/src/backend/port/sysv_shmem.c b/src/backend/port/sysv_shmem.c index 77cd8f3cca6..124b2148de9 100644 --- a/src/backend/port/sysv_shmem.c +++ b/src/backend/port/sysv_shmem.c @@ -102,8 +102,28 @@ static void * InternalIpcMemoryCreate(IpcMemoryKey memKey, Size size) { IpcMemoryId shmid; + void *requestedAddress = NULL; void *memAddress; + /* + * Normally we just pass requestedAddress = NULL to shmat(), allowing the + * system to choose where the segment gets mapped. But in an EXEC_BACKEND + * build, it's possible for whatever is chosen in the postmaster to not + * work for backends, due to variations in address space layout. As a + * rather klugy workaround, allow the user to specify the address to use + * via setting the environment variable PG_SHMEM_ADDR. (If this were of + * interest for anything except debugging, we'd probably create a cleaner + * and better-documented way to set it, such as a GUC.) + */ +#ifdef EXEC_BACKEND + { + char *pg_shmem_addr = getenv("PG_SHMEM_ADDR"); + + if (pg_shmem_addr) + requestedAddress = (void *) strtoul(pg_shmem_addr, NULL, 0); + } +#endif + shmid = shmget(memKey, size, IPC_CREAT | IPC_EXCL | IPCProtection); if (shmid < 0) @@ -203,10 +223,11 @@ InternalIpcMemoryCreate(IpcMemoryKey memKey, Size size) on_shmem_exit(IpcMemoryDelete, Int32GetDatum(shmid)); /* OK, should be able to attach to the segment */ - memAddress = shmat(shmid, NULL, PG_SHMAT_FLAGS); + memAddress = shmat(shmid, requestedAddress, PG_SHMAT_FLAGS); if (memAddress == (void *) -1) - elog(FATAL, "shmat(id=%d) failed: %m", shmid); + elog(FATAL, "shmat(id=%d, addr=%p, flags=0x%x) failed: %m", + shmid, requestedAddress, PG_SHMAT_FLAGS); /* Register on-exit routine to detach new segment before deleting */ on_shmem_exit(IpcMemoryDetach, PointerGetDatum(memAddress)); [parent: bfba563bc5d8]