Index: src/backend/postmaster/pgarch.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/postmaster/pgarch.c,v
retrieving revision 1.37
diff -c -r1.37 pgarch.c
*** src/backend/postmaster/pgarch.c	1 Jan 2008 19:45:51 -0000	1.37
--- src/backend/postmaster/pgarch.c	9 Jan 2008 23:13:33 -0000
***************
*** 267,284 ****
  static void
  pgarch_exit(SIGNAL_ARGS)
  {
! 	/*
! 	 * For now, we just nail the doors shut and get out of town.  It might
! 	 * seem cleaner to finish up any pending archive copies, but there's a
! 	 * nontrivial risk that init will kill us partway through.
! 	 */
! 	exit(0);
  }
  
! /* SIGHUP: set flag to re-read config file at next convenient time */
  static void
  ArchSigHupHandler(SIGNAL_ARGS)
  {
  	got_SIGHUP = true;
  }
  
--- 267,281 ----
  static void
  pgarch_exit(SIGNAL_ARGS)
  {
! 	/* SIGQUIT means curl up and die ... */
! 	exit(1);
  }
  
! /* SIGHUP signal handler for archiver process */
  static void
  ArchSigHupHandler(SIGNAL_ARGS)
  {
+ 	/* set flag to re-read config file at next convenient time */
  	got_SIGHUP = true;
  }
  
***************
*** 286,291 ****
--- 283,289 ----
  static void
  pgarch_waken(SIGNAL_ARGS)
  {
+ 	/* set flag that there is work to be done */
  	wakened = true;
  }
  
***************
*** 298,303 ****
--- 296,302 ----
  pgarch_MainLoop(void)
  {
  	time_t		last_copy_time = 0;
+ 	bool		postmaster_alive;
  
  	/*
  	 * We run the copy loop immediately upon entry, in case there are
***************
*** 309,314 ****
--- 308,316 ----
  
  	do
  	{
+ 		/* When the postmaster dies, we do one more archive cycle, then exit */
+ 		postmaster_alive = PostmasterIsAlive(true);
+ 
  		/* Check for config update */
  		if (got_SIGHUP)
  		{
***************
*** 334,340 ****
  		 * sleep into 1-second increments, and check for interrupts after each
  		 * nap.
  		 */
! 		while (!(wakened || got_SIGHUP))
  		{
  			time_t		curtime;
  
--- 336,342 ----
  		 * sleep into 1-second increments, and check for interrupts after each
  		 * nap.
  		 */
! 		while (!(wakened || got_SIGHUP || !PostmasterIsAlive(true)))
  		{
  			time_t		curtime;
  
***************
*** 344,350 ****
  				(unsigned int) PGARCH_AUTOWAKE_INTERVAL)
  				wakened = true;
  		}
! 	} while (PostmasterIsAlive(true));
  }
  
  /*
--- 346,352 ----
  				(unsigned int) PGARCH_AUTOWAKE_INTERVAL)
  				wakened = true;
  		}
! 	} while (postmaster_alive);
  }
  
  /*
Index: src/backend/postmaster/postmaster.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v
retrieving revision 1.550
diff -c -r1.550 postmaster.c
*** src/backend/postmaster/postmaster.c	1 Jan 2008 19:45:51 -0000	1.550
--- src/backend/postmaster/postmaster.c	9 Jan 2008 23:13:33 -0000
***************
*** 1315,1327 ****
  		/*
  		 * If we have lost the archiver, try to start a new one. We do this
  		 * even if we are shutting down, to allow archiver to take care of any
! 		 * remaining WAL files.
  		 */
! 		if (XLogArchivingActive() && PgArchPID == 0 && pmState >= PM_RUN)
  			PgArchPID = pgarch_start();
  
  		/* If we have lost the stats collector, try to start a new one */
! 		if (PgStatPID == 0 && pmState == PM_RUN)
  			PgStatPID = pgstat_start();
  
  		/*
--- 1315,1330 ----
  		/*
  		 * If we have lost the archiver, try to start a new one. We do this
  		 * even if we are shutting down, to allow archiver to take care of any
! 		 * remaining WAL files.  Once shutdown is done, though, don't restart
! 		 * it anymore.
  		 */
! 		if (XLogArchivingActive() && PgArchPID == 0 &&
! 			pmState >= PM_RUN && pmState <= PM_SHUTDOWN)
  			PgArchPID = pgarch_start();
  
  		/* If we have lost the stats collector, try to start a new one */
! 		if (PgStatPID == 0 &&
! 			pmState >= PM_RUN && pmState <= PM_SHUTDOWN)
  			PgStatPID = pgstat_start();
  
  		/*
***************
*** 2177,2186 ****
  				 *
  				 * At this point we should have no normal children left (else
  				 * we'd not be in PM_SHUTDOWN state) but we might have
! 				 * dead_end children.
  				 */
  				Assert(Shutdown > NoShutdown);
  				pmState = PM_WAIT_DEAD_END;
  			}
  			else
  			{
--- 2180,2197 ----
  				 *
  				 * At this point we should have no normal children left (else
  				 * we'd not be in PM_SHUTDOWN state) but we might have
! 				 * dead_end children.  We can also tell the archiver and
! 				 * stats collector processes to shut down.
  				 */
  				Assert(Shutdown > NoShutdown);
  				pmState = PM_WAIT_DEAD_END;
+ 
+ 				/* Waken archiver for the last time */
+ 				if (PgArchPID != 0 && Shutdown <= SmartShutdown)
+ 					signal_child(PgArchPID, SIGUSR1);
+ 				/* Tell pgstat to shut down; nothing left for it to do */
+ 				if (PgStatPID != 0)
+ 					signal_child(PgStatPID, SIGQUIT);
  			}
  			else
  			{
***************
*** 2235,2241 ****
  			if (!EXIT_STATUS_0(exitstatus))
  				LogChildExit(LOG, _("archiver process"),
  							 pid, exitstatus);
! 			if (XLogArchivingActive() && pmState >= PM_RUN)
  				PgArchPID = pgarch_start();
  			continue;
  		}
--- 2246,2253 ----
  			if (!EXIT_STATUS_0(exitstatus))
  				LogChildExit(LOG, _("archiver process"),
  							 pid, exitstatus);
! 			if (XLogArchivingActive() &&
! 				pmState >= PM_RUN && pmState <= PM_SHUTDOWN)
  				PgArchPID = pgarch_start();
  			continue;
  		}
***************
*** 2251,2257 ****
  			if (!EXIT_STATUS_0(exitstatus))
  				LogChildExit(LOG, _("statistics collector process"),
  							 pid, exitstatus);
! 			if (pmState == PM_RUN)
  				PgStatPID = pgstat_start();
  			continue;
  		}
--- 2263,2269 ----
  			if (!EXIT_STATUS_0(exitstatus))
  				LogChildExit(LOG, _("statistics collector process"),
  							 pid, exitstatus);
! 			if (pmState >= PM_RUN && pmState <= PM_SHUTDOWN)
  				PgStatPID = pgstat_start();
  			continue;
  		}
***************
*** 2563,2568 ****
--- 2575,2585 ----
  				 * change causes ServerLoop to stop creating new ones.
  				 */
  				pmState = PM_WAIT_DEAD_END;
+ 
+ 				/*
+ 				 * We already SIGQUIT'd the archiver and stats processes,
+ 				 * if any, when we entered FatalError state.
+ 				 */
  			}
  			else
  			{
***************
*** 2591,2603 ****
  					 */
  					FatalError = true;
  					pmState = PM_WAIT_DEAD_END;
  				}
- 				/* Tell pgarch to shut down too; nothing left for it to do */
- 				if (PgArchPID != 0)
- 					signal_child(PgArchPID, SIGQUIT);
- 				/* Tell pgstat to shut down too; nothing left for it to do */
- 				if (PgStatPID != 0)
- 					signal_child(PgStatPID, SIGQUIT);
  			}
  		}
  	}
--- 2608,2620 ----
  					 */
  					FatalError = true;
  					pmState = PM_WAIT_DEAD_END;
+ 
+ 					/* Kill the archiver and stats collector too */
+ 					if (PgArchPID != 0)
+ 						signal_child(PgArchPID, SIGQUIT);
+ 					if (PgStatPID != 0)
+ 						signal_child(PgStatPID, SIGQUIT);
  				}
  			}
  		}
  	}
***************
*** 2629,2641 ****
  	 * before init decides to SIGKILL us.)
  	 *
  	 * Note: we do not wait around for exit of the archiver or stats
! 	 * processes.  They've been sent SIGQUIT by this point (either when we
! 	 * entered PM_SHUTDOWN state, or when we set FatalError, and at least one
! 	 * of those must have happened by now).  In any case they contain logic to
! 	 * commit hara-kiri if they notice the postmaster is gone.	Since they
! 	 * aren't connected to shared memory, they pose no problem for shutdown.
! 	 * The syslogger is not considered either, since it's intended to survive
! 	 * till the postmaster exits.
  	 */
  	if (Shutdown > NoShutdown && pmState == PM_NO_CHILDREN)
  	{
--- 2646,2658 ----
  	 * before init decides to SIGKILL us.)
  	 *
  	 * Note: we do not wait around for exit of the archiver or stats
! 	 * processes.  They've been sent appropriate signals by this point (either
! 	 * when we entered PM_WAIT_DEAD_END state, or when we set FatalError, and
! 	 * at least one of those must have happened by now).  In any case they
! 	 * contain logic to commit hara-kiri if they notice the postmaster is
! 	 * gone.  Since they aren't connected to shared memory, they pose no
! 	 * problem for shutdown.  The syslogger is not considered either, since
! 	 * it's intended to survive till the postmaster exits.
  	 */
  	if (Shutdown > NoShutdown && pmState == PM_NO_CHILDREN)
  	{
