Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Detach shared memory from bgworkers without shmem access.
authorRobert Haas <rhaas@postgresql.org>
Wed, 7 May 2014 18:54:43 +0000 (14:54 -0400)
committerRobert Haas <rhaas@postgresql.org>
Wed, 7 May 2014 18:56:49 +0000 (14:56 -0400)
Since the postmaster won't perform a crash-and-restart sequence
for background workers which don't request shared memory access,
we'd better make sure that they can't corrupt shared memory.

Patch by me, review by Tom Lane.

src/backend/postmaster/bgworker.c

index a6b25d8494ab1d6df901d50da733809cb0715daa..8078a38ed725f8d8ec12c5aa7c1d9cc37f7eee86 100644 (file)
 #include "postmaster/bgworker_internals.h"
 #include "postmaster/postmaster.h"
 #include "storage/barrier.h"
+#include "storage/dsm.h"
 #include "storage/ipc.h"
 #include "storage/latch.h"
 #include "storage/lwlock.h"
+#include "storage/pg_shmem.h"
 #include "storage/pmsignal.h"
 #include "storage/proc.h"
 #include "storage/procsignal.h"
@@ -400,12 +402,16 @@ BackgroundWorkerStopNotifications(pid_t pid)
 BackgroundWorker *
 BackgroundWorkerEntry(int slotno)
 {
+   static BackgroundWorker myEntry;
    BackgroundWorkerSlot *slot;
 
    Assert(slotno < BackgroundWorkerData->total_slots);
    slot = &BackgroundWorkerData->slot[slotno];
    Assert(slot->in_use);
-   return &slot->worker;       /* can't become free while we're still here */
+
+   /* must copy this in case we don't intend to retain shmem access */
+   memcpy(&myEntry, &slot->worker, sizeof myEntry);
+   return &myEntry;
 }
 #endif
 
@@ -542,6 +548,20 @@ StartBackgroundWorker(void)
    snprintf(buf, MAXPGPATH, "bgworker: %s", worker->bgw_name);
    init_ps_display(buf, "", "", "");
 
+   /*
+    * If we're not supposed to have shared memory access, then detach from
+    * shared memory.  If we didn't request shared memory access, the
+    * postmaster won't force a cluster-wide restart if we exit unexpectedly,
+    * so we'd better make sure that we don't mess anything up that would
+    * require that sort of cleanup.
+    */
+   if ((worker->bgw_flags & BGWORKER_SHMEM_ACCESS) == 0)
+   {
+       on_exit_reset();
+       dsm_detach_all();
+       PGSharedMemoryDetach();
+   }
+
    SetProcessingMode(InitProcessing);
 
    /* Apply PostAuthDelay */
@@ -616,19 +636,29 @@ StartBackgroundWorker(void)
    /* We can now handle ereport(ERROR) */
    PG_exception_stack = &local_sigjmp_buf;
 
-   /* Early initialization */
-   BaseInit();
-
    /*
-    * If necessary, create a per-backend PGPROC struct in shared memory,
-    * except in the EXEC_BACKEND case where this was done in
-    * SubPostmasterMain. We must do this before we can use LWLocks (and in
-    * the EXEC_BACKEND case we already had to do some stuff with LWLocks).
+    * If the background worker request shared memory access, set that up now;
+    * else, detach all shared memory segments.
     */
-#ifndef EXEC_BACKEND
    if (worker->bgw_flags & BGWORKER_SHMEM_ACCESS)
+   {
+       /*
+        * Early initialization.  Some of this could be useful even for
+        * background workers that aren't using shared memory, but they can
+        * call the individual startup routines for those subsystems if needed.
+        */
+       BaseInit();
+
+       /*
+        * Create a per-backend PGPROC struct in shared memory, except in the
+        * EXEC_BACKEND case where this was done in SubPostmasterMain. We must
+        * do this before we can use LWLocks (and in the EXEC_BACKEND case we
+        * already had to do some stuff with LWLocks).
+        */
+#ifndef EXEC_BACKEND
        InitProcess();
 #endif
+   }
 
    /*
     * If bgw_main is set, we use that value as the initial entrypoint.