Ensure that any memory leaked during an error inside the bgwriter is
authorTom Lane <[email protected]>
Mon, 12 Sep 2005 22:20:30 +0000 (22:20 +0000)
committerTom Lane <[email protected]>
Mon, 12 Sep 2005 22:20:30 +0000 (22:20 +0000)
recovered.  I did not see any actual leak while testing this in CVS tip,
but 8.0 definitely has a problem with leaking the space temporarily
palloc'd by BufferSync().  In any case this seems a good idea to forestall
similar problems in future.  Per report from Arjen van der Meijden.

src/backend/postmaster/bgwriter.c

index 307e4d15b3bdcc2b2c9ffc21a999dd6d37db3d63..568058a8861b73bea7e5c7f862de72c24c1015d7 100644 (file)
@@ -155,6 +155,7 @@ void
 BackgroundWriterMain(void)
 {
        sigjmp_buf      local_sigjmp_buf;
+       MemoryContext bgwriter_context;
 
        Assert(BgWriterShmem != NULL);
        BgWriterShmem->bgwriter_pid = MyProcPid;
@@ -202,6 +203,19 @@ BackgroundWriterMain(void)
         */
        last_checkpoint_time = time(NULL);
 
+       /*
+        * Create a memory context that we will do all our work in.  We do this
+        * so that we can reset the context during error recovery and thereby
+        * avoid possible memory leaks.  Formerly this code just ran in
+        * TopMemoryContext, but resetting that would be a really bad idea.
+        */
+       bgwriter_context = AllocSetContextCreate(TopMemoryContext,
+                                                                                        "Background Writer",
+                                                                                        ALLOCSET_DEFAULT_MINSIZE,
+                                                                                        ALLOCSET_DEFAULT_INITSIZE,
+                                                                                        ALLOCSET_DEFAULT_MAXSIZE);
+       MemoryContextSwitchTo(bgwriter_context);
+
        /*
         * If an exception is encountered, processing resumes here.
         *
@@ -242,9 +256,12 @@ BackgroundWriterMain(void)
                 * Now return to normal top-level context and clear ErrorContext
                 * for next time.
                 */
-               MemoryContextSwitchTo(TopMemoryContext);
+               MemoryContextSwitchTo(bgwriter_context);
                FlushErrorState();
 
+               /* Flush any leaked data in the top-level context */
+               MemoryContextResetAndDeleteChildren(bgwriter_context);
+
                /* Now we can allow interrupts again */
                RESUME_INTERRUPTS();
 
@@ -509,6 +526,23 @@ RequestCheckpoint(bool waitforit)
        sig_atomic_t old_failed = bgs->ckpt_failed;
        sig_atomic_t old_started = bgs->ckpt_started;
 
+       /*
+        * If in a standalone backend, just do it ourselves.
+        */
+       if (!IsPostmasterEnvironment)
+       {
+               CreateCheckPoint(false, true);
+
+               /*
+                * After any checkpoint, close all smgr files.  This is so we
+                * won't hang onto smgr references to deleted files
+                * indefinitely.
+                */
+               smgrcloseall();
+
+               return;
+       }
+
        /*
         * Send signal to request checkpoint.  When waitforit is false, we
         * consider failure to send the signal to be nonfatal.