diff --git a/src/backend/access/transam/slru.c b/src/backend/access/transam/slru.c
index dff221bf27730e30b3e5bcca871b1e0efae1cbb4..57dcd2b33798c3e9230681bb5cfaee593903aa5a 100644
--- a/src/backend/access/transam/slru.c
+++ b/src/backend/access/transam/slru.c
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/backend/access/transam/slru.c,v 1.14 2004/05/28 05:12:42 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/access/transam/slru.c,v 1.15 2004/05/29 22:48:18 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -17,6 +17,7 @@
 #include <unistd.h>
 
 #include "access/slru.h"
+#include "postmaster/bgwriter.h"
 #include "storage/fd.h"
 #include "storage/lwlock.h"
 #include "miscadmin.h"
@@ -795,8 +796,8 @@ SimpleLruTruncate(SlruCtl ctl, int cutoffPage)
 	if (!SlruScanDirectory(ctl, cutoffPage, false))
 		return;					/* nothing to remove */
 
-	/* Perform a forced CHECKPOINT */
-	CreateCheckPoint(false, true);
+	/* Perform a CHECKPOINT */
+	RequestCheckpoint(true);
 
 	/*
 	 * Scan shared memory and remove any pages preceding the cutoff page,
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 348906ea4ac13ea7d326541cda4b41689eb8c8d0..cfb864d09411c096ac735a09a343d885b9a44d54 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.144 2004/05/28 05:12:42 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.145 2004/05/29 22:48:18 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -27,10 +27,10 @@
 #include "access/xlogutils.h"
 #include "catalog/catversion.h"
 #include "catalog/pg_control.h"
+#include "postmaster/bgwriter.h"
 #include "storage/bufpage.h"
 #include "storage/fd.h"
 #include "storage/lwlock.h"
-#include "storage/pmsignal.h"
 #include "storage/proc.h"
 #include "storage/sinval.h"
 #include "storage/spin.h"
@@ -1206,9 +1206,9 @@ XLogWrite(XLogwrtRqst WriteRqst)
 				{
 #ifdef WAL_DEBUG
 					if (XLOG_DEBUG)
-						elog(LOG, "time for a checkpoint, signaling postmaster");
+						elog(LOG, "time for a checkpoint, signaling bgwriter");
 #endif
-					SendPostmasterSignal(PMSIGNAL_DO_CHECKPOINT);
+					RequestCheckpoint(false);
 				}
 			}
 			LWLockRelease(ControlFileLock);
@@ -3087,11 +3087,6 @@ StartupXLOG(void)
 				RmgrTable[rmid].rm_cleanup();
 		}
 
-		/* suppress in-transaction check in CreateCheckPoint */
-		MyLastRecPtr.xrecoff = 0;
-		MyXactMadeXLogEntry = false;
-		MyXactMadeTempRelUpdate = false;
-
 		/*
 		 * At this point, ThisStartUpID is the largest SUI that we could
 		 * find evidence for in the WAL entries.  But check it against
@@ -3293,11 +3288,6 @@ ShutdownXLOG(int code, Datum arg)
 	ereport(LOG,
 			(errmsg("shutting down")));
 
-	/* suppress in-transaction check in CreateCheckPoint */
-	MyLastRecPtr.xrecoff = 0;
-	MyXactMadeXLogEntry = false;
-	MyXactMadeTempRelUpdate = false;
-
 	CritSectionCount++;
 	CreateCheckPoint(true, true);
 	ShutdownCLOG();
@@ -3324,27 +3314,13 @@ CreateCheckPoint(bool shutdown, bool force)
 	uint32		_logId;
 	uint32		_logSeg;
 
-	if (MyXactMadeXLogEntry)
-		ereport(ERROR,
-				(errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
-		  errmsg("checkpoint cannot be made inside transaction block")));
-
 	/*
 	 * Acquire CheckpointLock to ensure only one checkpoint happens at a
-	 * time.
-	 *
-	 * The CheckpointLock can be held for quite a while, which is not good
-	 * because we won't respond to a cancel/die request while waiting for
-	 * an LWLock.  (But the alternative of using a regular lock won't work
-	 * for background checkpoint processes, which are not regular
-	 * backends.)  So, rather than use a plain LWLockAcquire, use this
-	 * kluge to allow an interrupt to be accepted while we are waiting:
+	 * time.  (This is just pro forma, since in the present system
+	 * structure there is only one process that is allowed to issue
+	 * checkpoints at any given time.)
 	 */
-	while (!LWLockConditionalAcquire(CheckpointLock, LW_EXCLUSIVE))
-	{
-		CHECK_FOR_INTERRUPTS();
-		pg_usleep(1000000L);
-	}
+	LWLockAcquire(CheckpointLock, LW_EXCLUSIVE);
 
 	/*
 	 * Use a critical section to force system panic if we have trouble.
diff --git a/src/backend/bootstrap/bootstrap.c b/src/backend/bootstrap/bootstrap.c
index ed42bf133c7fc97a8016f16092f5d7eef5074b96..a19217a47b2631b1cafc0469ee7fa926ec66f7b1 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
- *	  $PostgreSQL: pgsql/src/backend/bootstrap/bootstrap.c,v 1.181 2004/05/28 05:12:45 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/bootstrap/bootstrap.c,v 1.182 2004/05/29 22:48:18 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -33,6 +33,7 @@
 #include "executor/executor.h"
 #include "libpq/pqsignal.h"
 #include "miscadmin.h"
+#include "postmaster/bgwriter.h"
 #include "pgtime.h"
 #include "storage/freespace.h"
 #include "storage/ipc.h"
@@ -50,6 +51,8 @@
 #define ALLOC(t, c)		((t *) calloc((unsigned)(c), sizeof(t)))
 
 extern int	Int_yyparse(void);
+static void usage(void);
+static void bootstrap_signals(void);
 static hashnode *AddStr(char *str, int strlength, int mderef);
 static Form_pg_attribute AllocateAttribute(void);
 static bool BootstrapAlreadySeen(Oid id);
@@ -192,44 +195,8 @@ typedef struct _IndexList
 static IndexList *ILHead = NULL;
 
 
-/* ----------------------------------------------------------------
- *						misc functions
- * ----------------------------------------------------------------
- */
-
-/* ----------------
- *		error handling / abort routines
- * ----------------
- */
-void
-err_out(void)
-{
-	Warnings++;
-	cleanup();
-}
-
-/* usage:
- *		usage help for the bootstrap backend
- */
-static void
-usage(void)
-{
-	fprintf(stderr,
-			gettext("Usage:\n"
-					"  postgres -boot [OPTION]... DBNAME\n"
-					"  -c NAME=VALUE    set run-time parameter\n"
-					"  -d 1-5           debug level\n"
-					"  -D datadir       data directory\n"
-					"  -F               turn off fsync\n"
-					"  -o file          send debug output to file\n"
-					"  -x num           internal use\n"));
-
-	proc_exit(1);
-}
-
-
 /*
- *	 The main loop for running the backend in bootstrap mode
+ *	 The main entry point for running the backend in bootstrap mode
  *
  *	 The bootstrap mode is used to initialize the template database.
  *	 The bootstrap backend doesn't speak SQL, but instead expects
@@ -387,19 +354,13 @@ BootstrapMain(int argc, char *argv[])
 		switch (xlogop)
 		{
 			case BS_XLOG_STARTUP:
-				statmsg = "startup subprocess";
-				break;
-			case BS_XLOG_CHECKPOINT:
-				statmsg = "checkpoint subprocess";
+				statmsg = "startup process";
 				break;
 			case BS_XLOG_BGWRITER:
-				statmsg = "bgwriter subprocess";
-				break;
-			case BS_XLOG_SHUTDOWN:
-				statmsg = "shutdown subprocess";
+				statmsg = "writer process";
 				break;
 			default:
-				statmsg = "??? subprocess";
+				statmsg = "??? process";
 				break;
 		}
 		init_ps_display(statmsg, "", "");
@@ -415,48 +376,9 @@ BootstrapMain(int argc, char *argv[])
 		pg_timezone_initialize();
 	}
 
-	if (IsUnderPostmaster)
-	{
-		/*
-		 * Properly accept or ignore signals the postmaster might send us
-		 */
-		pqsignal(SIGHUP, SIG_IGN);
-		pqsignal(SIGINT, SIG_IGN);		/* ignore query-cancel */
-		pqsignal(SIGTERM, die);
-		pqsignal(SIGQUIT, quickdie);
-		pqsignal(SIGALRM, SIG_IGN);
-		pqsignal(SIGPIPE, SIG_IGN);
-		pqsignal(SIGUSR1, SIG_IGN);
-		pqsignal(SIGUSR2, SIG_IGN);
-
-		/*
-		 * Reset some signals that are accepted by postmaster but not here
-		 */
-		pqsignal(SIGCHLD, SIG_DFL);
-		pqsignal(SIGTTIN, SIG_DFL);
-		pqsignal(SIGTTOU, SIG_DFL);
-		pqsignal(SIGCONT, SIG_DFL);
-		pqsignal(SIGWINCH, SIG_DFL);
-
-		/*
-		 * Unblock signals (they were blocked when the postmaster forked
-		 * us)
-		 */
-		PG_SETMASK(&UnBlockSig);
-	}
-	else
-	{
-		/* Set up appropriately for interactive use */
-		pqsignal(SIGHUP, die);
-		pqsignal(SIGINT, die);
-		pqsignal(SIGTERM, die);
-		pqsignal(SIGQUIT, die);
-
-		/*
-		 * Create lockfile for data directory.
-		 */
+	/* If standalone, create lockfile for data directory */
+	if (!IsUnderPostmaster)
 		CreateDataDirLockFile(DataDir, false);
-	}
 
 	SetProcessingMode(BootstrapProcessing);
 	IgnoreSystemIndexes(true);
@@ -488,37 +410,30 @@ BootstrapMain(int argc, char *argv[])
 	switch (xlogop)
 	{
 		case BS_XLOG_NOP:
+			bootstrap_signals();
 			break;
 
 		case BS_XLOG_BOOTSTRAP:
+			bootstrap_signals();
 			BootStrapXLOG();
 			StartupXLOG();
 			break;
 
-		case BS_XLOG_CHECKPOINT:
-			InitXLOGAccess();
-			CreateCheckPoint(false, false);
-			proc_exit(0);		/* done */
-
-		case BS_XLOG_BGWRITER:
-			InitXLOGAccess();
-			BufferBackgroundWriter();
-			proc_exit(0);		/* done */
-
 		case BS_XLOG_STARTUP:
+			bootstrap_signals();
 			StartupXLOG();
 			LoadFreeSpaceMap();
-			proc_exit(0);		/* done */
+			proc_exit(0);		/* startup done */
 
-		case BS_XLOG_SHUTDOWN:
+		case BS_XLOG_BGWRITER:
+			/* don't set signals, bgwriter has its own agenda */
 			InitXLOGAccess();
-			ShutdownXLOG(0, 0);
-			DumpFreeSpaceMap(0, 0);
-			proc_exit(0);		/* done */
+			BackgroundWriterMain();
+			proc_exit(1);		/* should never return */
 
 		default:
 			elog(PANIC, "unrecognized XLOG op: %d", xlogop);
-			proc_exit(0);
+			proc_exit(1);
 	}
 
 	SetProcessingMode(BootstrapProcessing);
@@ -575,9 +490,90 @@ BootstrapMain(int argc, char *argv[])
 
 	/* not reached, here to make compiler happy */
 	return 0;
+}
+
+
+/* ----------------------------------------------------------------
+ *						misc functions
+ * ----------------------------------------------------------------
+ */
+
+/* usage:
+ *		usage help for the bootstrap backend
+ */
+static void
+usage(void)
+{
+	fprintf(stderr,
+			gettext("Usage:\n"
+					"  postgres -boot [OPTION]... DBNAME\n"
+					"  -c NAME=VALUE    set run-time parameter\n"
+					"  -d 1-5           debug level\n"
+					"  -D datadir       data directory\n"
+					"  -F               turn off fsync\n"
+					"  -o file          send debug output to file\n"
+					"  -x num           internal use\n"));
+
+	proc_exit(1);
+}
+
+/*
+ * Set up signal handling for a bootstrap process
+ */
+static void
+bootstrap_signals(void)
+{
+	if (IsUnderPostmaster)
+	{
+		/*
+		 * Properly accept or ignore signals the postmaster might send us
+		 */
+		pqsignal(SIGHUP, SIG_IGN);
+		pqsignal(SIGINT, SIG_IGN);		/* ignore query-cancel */
+		pqsignal(SIGTERM, die);
+		pqsignal(SIGQUIT, quickdie);
+		pqsignal(SIGALRM, SIG_IGN);
+		pqsignal(SIGPIPE, SIG_IGN);
+		pqsignal(SIGUSR1, SIG_IGN);
+		pqsignal(SIGUSR2, SIG_IGN);
 
+		/*
+		 * Reset some signals that are accepted by postmaster but not here
+		 */
+		pqsignal(SIGCHLD, SIG_DFL);
+		pqsignal(SIGTTIN, SIG_DFL);
+		pqsignal(SIGTTOU, SIG_DFL);
+		pqsignal(SIGCONT, SIG_DFL);
+		pqsignal(SIGWINCH, SIG_DFL);
+
+		/*
+		 * Unblock signals (they were blocked when the postmaster forked
+		 * us)
+		 */
+		PG_SETMASK(&UnBlockSig);
+	}
+	else
+	{
+		/* Set up appropriately for interactive use */
+		pqsignal(SIGHUP, die);
+		pqsignal(SIGINT, die);
+		pqsignal(SIGTERM, die);
+		pqsignal(SIGQUIT, die);
+	}
+}
+
+/* ----------------
+ *		error handling / abort routines
+ * ----------------
+ */
+void
+err_out(void)
+{
+	Warnings++;
+	cleanup();
 }
 
+
 /* ----------------------------------------------------------------
  *				MANUAL BACKEND INTERACTIVE INTERFACE COMMANDS
  * ----------------------------------------------------------------
diff --git a/src/backend/libpq/pqsignal.c b/src/backend/libpq/pqsignal.c
index dc1f6ccc0871b6a0defb1c3deaef56b51e63d660..468c062aa4330cf041c125ea767cae8cb7fb00a5 100644
--- a/src/backend/libpq/pqsignal.c
+++ b/src/backend/libpq/pqsignal.c
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/libpq/pqsignal.c,v 1.33 2004/04/12 16:19:18 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/libpq/pqsignal.c,v 1.34 2004/05/29 22:48:19 tgl Exp $
  *
  * NOTES
  *		This shouldn't be in libpq, but the monitor and some other
@@ -46,6 +46,17 @@
 #include "libpq/pqsignal.h"
 
 
+#ifdef HAVE_SIGPROCMASK
+sigset_t	UnBlockSig,
+			BlockSig,
+			AuthBlockSig;
+#else
+int			UnBlockSig,
+			BlockSig,
+			AuthBlockSig;
+#endif
+
+
 /*
  * Initialize BlockSig, UnBlockSig, and AuthBlockSig.
  *
@@ -153,4 +164,5 @@ pqsignal(int signo, pqsigfunc func)
 	return oact.sa_handler;
 #endif   /* !HAVE_POSIX_SIGNALS */
 }
+
 #endif /* WIN32 */
diff --git a/src/backend/main/main.c b/src/backend/main/main.c
index 272d4cc0d0a0bad3cbbc73e522d4089219acf774..aee2da0731503398e960c985b2fb179383f30ffa 100644
--- a/src/backend/main/main.c
+++ b/src/backend/main/main.c
@@ -13,7 +13,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/main/main.c,v 1.84 2004/05/28 05:12:50 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/main/main.c,v 1.85 2004/05/29 22:48:19 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -34,12 +34,13 @@
 #include <sys/param.h>
 #endif
 
-#include "miscadmin.h"
 #include "bootstrap/bootstrap.h"
+#include "miscadmin.h"
+#include "pgstat.h"
+#include "postmaster/postmaster.h"
 #include "tcop/tcopprot.h"
 #include "utils/help_config.h"
 #include "utils/ps_status.h"
-#include "pgstat.h"
 #ifdef WIN32
 #include "libpq/pqsignal.h"
 #endif
diff --git a/src/backend/postmaster/Makefile b/src/backend/postmaster/Makefile
index b56881fc86eff6b97d363127c75cce2bdb1a864e..489c6d921123c8e93c84d9a80b0f7509d75897fa 100644
--- a/src/backend/postmaster/Makefile
+++ b/src/backend/postmaster/Makefile
@@ -1,10 +1,10 @@
 #-------------------------------------------------------------------------
 #
 # Makefile--
-#    Makefile for postmaster
+#    Makefile for src/backend/postmaster
 #
 # IDENTIFICATION
-#    $PostgreSQL: pgsql/src/backend/postmaster/Makefile,v 1.14 2003/11/29 19:51:55 pgsql Exp $
+#    $PostgreSQL: pgsql/src/backend/postmaster/Makefile,v 1.15 2004/05/29 22:48:19 tgl Exp $
 #
 #-------------------------------------------------------------------------
 
@@ -12,7 +12,7 @@ subdir = src/backend/postmaster
 top_builddir = ../../..
 include $(top_builddir)/src/Makefile.global
 
-OBJS = postmaster.o pgstat.o
+OBJS = postmaster.o bgwriter.o pgstat.o
 
 all: SUBSYS.o
 
diff --git a/src/backend/postmaster/bgwriter.c b/src/backend/postmaster/bgwriter.c
new file mode 100644
index 0000000000000000000000000000000000000000..ce80a4feff7a6454152d6c154cca5c50296c975d
--- /dev/null
+++ b/src/backend/postmaster/bgwriter.c
@@ -0,0 +1,456 @@
+/*-------------------------------------------------------------------------
+ *
+ * bgwriter.c
+ *
+ * The background writer (bgwriter) is new in Postgres 7.5.  It attempts
+ * to keep regular backends from having to write out dirty shared buffers
+ * (which they would only do when needing to free a shared buffer to read in
+ * another page).  In the best scenario all writes from shared buffers will
+ * be issued by the background writer process.  However, regular backends are
+ * still empowered to issue writes if the bgwriter fails to maintain enough
+ * clean shared buffers.
+ *
+ * The bgwriter is also charged with handling all checkpoints.  It will
+ * automatically dispatch a checkpoint after a certain amount of time has
+ * elapsed since the last one, and it can be signaled to perform requested
+ * checkpoints as well.  (The GUC parameter that mandates a checkpoint every
+ * so many WAL segments is implemented by having backends signal the bgwriter
+ * when they fill WAL segments; the bgwriter itself doesn't watch for the
+ * condition.)
+ *
+ * The bgwriter is started by the postmaster as soon as the startup subprocess
+ * finishes.  It remains alive until the postmaster commands it to terminate.
+ * Normal termination is by SIGUSR2, which instructs the bgwriter to execute
+ * a shutdown checkpoint and then exit(0).  (All backends must be stopped
+ * before SIGUSR2 is issued!)  Emergency termination is by SIGQUIT; like any
+ * backend, the bgwriter will simply abort and exit on SIGQUIT.
+ *
+ * If the bgwriter exits unexpectedly, the postmaster treats that the same
+ * as a backend crash: shared memory may be corrupted, so remaining backends
+ * should be killed by SIGQUIT and then a recovery cycle started.
+ *
+ *
+ * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
+ *
+ *
+ * IDENTIFICATION
+ *	  $PostgreSQL: pgsql/src/backend/postmaster/bgwriter.c,v 1.1 2004/05/29 22:48:19 tgl Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include <signal.h>
+
+#include "access/xlog.h"
+#include "libpq/pqsignal.h"
+#include "miscadmin.h"
+#include "postmaster/bgwriter.h"
+#include "storage/bufmgr.h"
+#include "storage/freespace.h"
+#include "storage/ipc.h"
+#include "storage/pmsignal.h"
+#include "storage/smgr.h"
+#include "tcop/tcopprot.h"
+#include "utils/guc.h"
+
+
+/*
+ * Shared memory area for communication between bgwriter and backends
+ */
+typedef struct
+{
+	pid_t	bgwriter_pid;		/* PID of bgwriter (0 if not started) */
+	sig_atomic_t	checkpoint_count; /* advances when checkpoint done */
+} BgWriterShmemStruct;
+
+static BgWriterShmemStruct *BgWriterShmem;
+
+/*
+ * GUC parameters
+ */
+int			BgWriterDelay = 200;
+int			BgWriterPercent = 1;
+int			BgWriterMaxPages = 100;
+
+int			CheckPointTimeout = 300;
+int			CheckPointWarning = 30;
+
+/*
+ * Flags set by interrupt handlers for later service in the main loop.
+ */
+static volatile sig_atomic_t got_SIGHUP = false;
+static volatile sig_atomic_t checkpoint_requested = false;
+static volatile sig_atomic_t shutdown_requested = false;
+
+/*
+ * Private state
+ */
+static time_t	last_checkpoint_time;
+
+
+static void bg_quickdie(SIGNAL_ARGS);
+static void BgSigHupHandler(SIGNAL_ARGS);
+static void ReqCheckpointHandler(SIGNAL_ARGS);
+static void ReqShutdownHandler(SIGNAL_ARGS);
+
+
+/*
+ * Main entry point for bgwriter process
+ *
+ * This is invoked from BootstrapMain, which has already created the basic
+ * execution environment, but not enabled signals yet.
+ */
+void
+BackgroundWriterMain(void)
+{
+	Assert(BgWriterShmem != NULL);
+	BgWriterShmem->bgwriter_pid = MyProcPid;
+
+	/*
+	 * Properly accept or ignore signals the postmaster might send us
+	 *
+	 * Note: we deliberately ignore SIGTERM, because during a standard Unix
+	 * system shutdown cycle, init will SIGTERM all processes at once.  We
+	 * want to wait for the backends to exit, whereupon the postmaster will
+	 * tell us it's okay to shut down (via SIGUSR2).
+	 *
+	 * SIGUSR1 is presently unused; keep it spare in case someday we want
+	 * this process to participate in sinval messaging.
+	 */
+	pqsignal(SIGHUP, BgSigHupHandler);	/* set flag to read config file */
+	pqsignal(SIGINT, ReqCheckpointHandler);		/* request checkpoint */
+	pqsignal(SIGTERM, SIG_IGN);			/* ignore SIGTERM */
+	pqsignal(SIGQUIT, bg_quickdie);		/* hard crash time */
+	pqsignal(SIGALRM, SIG_IGN);
+	pqsignal(SIGPIPE, SIG_IGN);
+	pqsignal(SIGUSR1, SIG_IGN);			/* reserve for sinval */
+	pqsignal(SIGUSR2, ReqShutdownHandler);		/* request shutdown */
+
+	/*
+	 * Reset some signals that are accepted by postmaster but not here
+	 */
+	pqsignal(SIGCHLD, SIG_DFL);
+	pqsignal(SIGTTIN, SIG_DFL);
+	pqsignal(SIGTTOU, SIG_DFL);
+	pqsignal(SIGCONT, SIG_DFL);
+	pqsignal(SIGWINCH, SIG_DFL);
+
+	/* We allow SIGQUIT (quickdie) at all times */
+#ifdef HAVE_SIGPROCMASK
+	sigdelset(&BlockSig, SIGQUIT);
+#else
+	BlockSig &= ~(sigmask(SIGQUIT));
+#endif
+
+	/*
+	 * Initialize so that first time-driven checkpoint happens
+	 * at the correct time.
+	 */
+	last_checkpoint_time = time(NULL);
+
+	/*
+	 * If an exception is encountered, processing resumes here.
+	 */
+	if (sigsetjmp(Warn_restart, 1) != 0)
+	{
+		/*
+		 * Make sure we're not interrupted while cleaning up.  Also forget
+		 * any pending QueryCancel request, since we're aborting anyway.
+		 * Force InterruptHoldoffCount to a known state in case we
+		 * ereport'd from inside a holdoff section.
+		 */
+		ImmediateInterruptOK = false;
+		QueryCancelPending = false;
+		InterruptHoldoffCount = 1;
+		CritSectionCount = 0;	/* should be unnecessary, but... */
+
+		/*
+		 * These operations are really just a minimal subset of
+		 * AbortTransaction().  We don't have very many resources
+		 * to worry about in bgwriter, but we do have LWLocks and buffers.
+		 */
+		LWLockReleaseAll();
+		AbortBufferIO();
+		UnlockBuffers();
+
+		/*
+		 * Clear flag to indicate that we got out of error recovery mode
+		 * successfully.  (Flag was set in elog.c before longjmp().)
+		 */
+		InError = false;
+
+		/*
+		 * Exit interrupt holdoff section we implicitly established above.
+		 */
+		RESUME_INTERRUPTS();
+
+		/*
+		 * Sleep at least 1 second after any error.  A write error is
+		 * likely to be repeated, and we don't want to be filling the
+		 * error logs as fast as we can.  (XXX think about ways to make
+		 * progress when the LRU dirty buffer cannot be written...)
+		 */
+		pg_usleep(1000000L);
+	}
+
+	Warn_restart_ready = true;	/* we can now handle ereport(ERROR) */
+
+	/*
+	 * Unblock signals (they were blocked when the postmaster forked us)
+	 */
+	PG_SETMASK(&UnBlockSig);
+
+	/*
+	 * Loop forever 
+	 */
+	for (;;)
+	{
+		bool		do_checkpoint = false;
+		bool		force_checkpoint = false;
+		time_t		now;
+		int			elapsed_secs;
+		int			n;
+		long		udelay;
+
+		/*
+		 * Process any signals received recently.
+		 */
+		if (got_SIGHUP)
+		{
+			got_SIGHUP = false;
+			ProcessConfigFile(PGC_SIGHUP);
+		}
+		if (checkpoint_requested)
+		{
+			checkpoint_requested = false;
+			do_checkpoint = true;
+			force_checkpoint = true;
+		}
+		if (shutdown_requested)
+		{
+			ShutdownXLOG(0, 0);
+			DumpFreeSpaceMap(0, 0);
+			/* Normal exit from the bgwriter is here */
+			proc_exit(0);		/* done */
+		}
+
+		/*
+		 * Do an unforced checkpoint if too much time has elapsed
+		 * since the last one.
+		 */
+		now = time(NULL);
+		elapsed_secs = now - last_checkpoint_time;
+		if (elapsed_secs >= CheckPointTimeout)
+			do_checkpoint = true;
+
+		/*
+		 * Do a checkpoint if requested, otherwise do one cycle of
+		 * dirty-buffer writing.
+		 */
+		if (do_checkpoint)
+		{
+			if (CheckPointWarning != 0)
+			{
+				/*
+				 * Ideally we should only warn if this checkpoint was
+				 * requested due to running out of segment files, and not
+				 * if it was manually requested.  However we can't tell the
+				 * difference with the current signalling mechanism.
+				 */
+				if (elapsed_secs < CheckPointWarning)
+					ereport(LOG,
+							(errmsg("checkpoints are occurring too frequently (%d seconds apart)",
+									elapsed_secs),
+							 errhint("Consider increasing the configuration parameter \"checkpoint_segments\".")));
+			}
+
+			CreateCheckPoint(false, force_checkpoint);
+
+			/*
+			 * Note we record the checkpoint start time not end time as
+			 * last_checkpoint_time.  This is so that time-driven checkpoints
+			 * happen at a predictable spacing.
+			 */
+			last_checkpoint_time = now;
+
+			/*
+			 * Indicate checkpoint completion to any waiting backends.
+			 */
+			BgWriterShmem->checkpoint_count++;
+
+			/*
+			 * After any checkpoint, close all smgr files.  This is so we
+			 * won't hang onto smgr references to deleted files indefinitely.
+			 */
+			smgrcloseall();
+
+			/* Nap for configured time before rechecking */
+			n = 1;
+		}
+		else
+		{
+			n = BufferSync(BgWriterPercent, BgWriterMaxPages);
+		}
+
+		/*
+		 * Nap for the configured time or sleep for 10 seconds if
+		 * there was nothing to do at all.
+		 *
+		 * On some platforms, signals won't interrupt the sleep.  To ensure
+		 * we respond reasonably promptly when someone signals us,
+		 * break down the sleep into 1-second increments, and check for
+		 * interrupts after each nap.
+		 */
+		udelay = ((n > 0) ? BgWriterDelay : 10000) * 1000L;
+		while (udelay > 1000000L)
+		{
+			if (got_SIGHUP || checkpoint_requested || shutdown_requested)
+				break;
+			pg_usleep(1000000L);
+			udelay -= 1000000L;
+		}
+		if (!(got_SIGHUP || checkpoint_requested || shutdown_requested))
+			pg_usleep(udelay);
+
+		/*
+		 * Emergency bailout if postmaster has died.  This is to avoid the
+		 * necessity for manual cleanup of all postmaster children.
+		 */
+		if (!PostmasterIsAlive(true))
+			exit(1);
+	}
+}
+
+
+/* --------------------------------
+ *		signal handler routines
+ * --------------------------------
+ */
+
+/*
+ * bg_quickdie() occurs when signalled SIGQUIT by the postmaster.
+ *
+ * Some backend has bought the farm,
+ * so we need to stop what we're doing and exit.
+ */
+static void
+bg_quickdie(SIGNAL_ARGS)
+{
+	PG_SETMASK(&BlockSig);
+
+	/*
+	 * DO NOT proc_exit() -- we're here because shared memory may be
+	 * corrupted, so we don't want to try to clean up our transaction.
+	 * Just nail the windows shut and get out of town.
+	 *
+	 * Note we do exit(1) not exit(0).	This is to force the postmaster into
+	 * a system reset cycle if some idiot DBA sends a manual SIGQUIT to a
+	 * random backend.	This is necessary precisely because we don't clean
+	 * up our shared memory state.
+	 */
+	exit(1);
+}
+
+/* SIGHUP: set flag to re-read config file at next convenient time */
+static void
+BgSigHupHandler(SIGNAL_ARGS)
+{
+	got_SIGHUP = true;
+}
+
+/* SIGINT: set flag to run a normal checkpoint right away */
+static void
+ReqCheckpointHandler(SIGNAL_ARGS)
+{
+	checkpoint_requested = true;
+}
+
+/* SIGUSR2: set flag to run a shutdown checkpoint and exit */
+static void
+ReqShutdownHandler(SIGNAL_ARGS)
+{
+	shutdown_requested = true;
+}
+
+
+/* --------------------------------
+ *		communication with backends
+ * --------------------------------
+ */
+
+/*
+ * BgWriterShmemSize
+ *		Compute space needed for bgwriter-related shared memory
+ */
+int
+BgWriterShmemSize(void)
+{
+	/*
+	 * This is not worth measuring right now, but may become so after we
+	 * add fsync signaling ...
+	 */
+	return MAXALIGN(sizeof(BgWriterShmemStruct));
+}
+
+/*
+ * BgWriterShmemInit
+ *		Allocate and initialize bgwriter-related shared memory
+ */
+void
+BgWriterShmemInit(void)
+{
+	bool found;
+
+	BgWriterShmem = (BgWriterShmemStruct *)
+		ShmemInitStruct("Background Writer Data",
+						sizeof(BgWriterShmemStruct),
+						&found);
+	if (BgWriterShmem == NULL)
+		ereport(FATAL,
+				(errcode(ERRCODE_OUT_OF_MEMORY),
+				 errmsg("insufficient shared memory for bgwriter")));
+	if (found)
+		return;					/* already initialized */
+
+	MemSet(BgWriterShmem, 0, sizeof(BgWriterShmemStruct));
+}
+
+/*
+ * RequestCheckpoint
+ *		Called in backend processes to request an immediate checkpoint
+ *
+ * If waitforit is true, wait until the checkpoint is completed
+ * before returning; otherwise, just signal the request and return
+ * immediately.
+ */
+void
+RequestCheckpoint(bool waitforit)
+{
+	volatile sig_atomic_t *count_ptr = &BgWriterShmem->checkpoint_count;
+	sig_atomic_t	old_count = *count_ptr;
+
+	/*
+	 * Send signal to request checkpoint.  When waitforit is false,
+	 * we consider failure to send the signal to be nonfatal.
+	 */
+	if (BgWriterShmem->bgwriter_pid == 0)
+		elog(waitforit ? ERROR : LOG,
+			 "could not request checkpoint because bgwriter not running");
+	if (kill(BgWriterShmem->bgwriter_pid, SIGINT) != 0)
+		elog(waitforit ? ERROR : LOG,
+			 "could not signal for checkpoint: %m");
+
+	/*
+	 * If requested, wait for completion.  We detect completion by
+	 * observing a change in checkpoint_count in shared memory.
+	 */
+	if (waitforit)
+	{
+		while (*count_ptr == old_count)
+		{
+			CHECK_FOR_INTERRUPTS();
+			pg_usleep(1000000L);
+		}
+	}
+}
diff --git a/src/backend/postmaster/pgstat.c b/src/backend/postmaster/pgstat.c
index a3a4e57c85594048e4f3ccd1f1ffe6484a93234f..c90749ca12763f717e3698ca4eb5fb922c3ee979 100644
--- a/src/backend/postmaster/pgstat.c
+++ b/src/backend/postmaster/pgstat.c
@@ -13,7 +13,7 @@
  *
  *	Copyright (c) 2001-2003, PostgreSQL Global Development Group
  *
- *	$PostgreSQL: pgsql/src/backend/postmaster/pgstat.c,v 1.72 2004/05/28 05:12:58 tgl Exp $
+ *	$PostgreSQL: pgsql/src/backend/postmaster/pgstat.c,v 1.73 2004/05/29 22:48:19 tgl Exp $
  * ----------
  */
 #include "postgres.h"
@@ -32,23 +32,25 @@
 
 #include "pgstat.h"
 
-#include "access/xact.h"
 #include "access/heapam.h"
+#include "access/xact.h"
 #include "catalog/catname.h"
-#include "catalog/pg_shadow.h"
 #include "catalog/pg_database.h"
-#include "libpq/pqsignal.h"
+#include "catalog/pg_shadow.h"
 #include "libpq/libpq.h"
+#include "libpq/pqsignal.h"
 #include "mb/pg_wchar.h"
 #include "miscadmin.h"
-#include "utils/memutils.h"
+#include "postmaster/postmaster.h"
 #include "storage/backendid.h"
 #include "storage/ipc.h"
 #include "storage/pg_shmem.h"
+#include "storage/pmsignal.h"
 #include "tcop/tcopprot.h"
-#include "utils/rel.h"
 #include "utils/hsearch.h"
+#include "utils/memutils.h"
 #include "utils/ps_status.h"
+#include "utils/rel.h"
 #include "utils/syscache.h"
 
 
@@ -75,8 +77,6 @@ bool		pgstat_is_running = false;
 NON_EXEC_STATIC int	pgStatSock = -1;
 static int	pgStatPipe[2];
 static struct sockaddr_storage pgStatAddr;
-static int	pgStatPmPipe[2] = {-1, -1};
-static int  pgStatCollectorPmPipe[2] = {-1, -1};
 
 static int	pgStatPid;
 static time_t last_pgstat_start_time;
@@ -397,17 +397,6 @@ pgstat_init(void)
 		goto startup_failed;
 	}
 
-	/*
-	 * Create the pipe that controls the statistics collector shutdown
-	 */
-	if (pgpipe(pgStatPmPipe) < 0 || pgpipe(pgStatCollectorPmPipe) < 0)
-	{
-		ereport(LOG,
-				(errcode_for_socket_access(),
-		  errmsg("could not create pipe for statistics collector: %m")));
-		goto startup_failed;
-	}
-
 	freeaddrinfo_all(hints.ai_family, addrs);
 
 	return;
@@ -439,9 +428,9 @@ startup_failed:
 static pid_t
 pgstat_forkexec(STATS_PROCESS_TYPE procType)
 {
-	char *av[12];
+	char *av[10];
 	int ac = 0, bufc = 0, i;
-	char pgstatBuf[7][32];
+	char pgstatBuf[2][32];
 
 	av[ac++] = "postgres";
 
@@ -464,11 +453,7 @@ pgstat_forkexec(STATS_PROCESS_TYPE procType)
 	/* postgres_exec_path is not passed by write_backend_variables */
 	av[ac++] = postgres_exec_path;
 
-	/* Sockets + pipes (those not passed by write_backend_variables) */
-	snprintf(pgstatBuf[bufc++],32,"%d",pgStatPmPipe[0]);
-	snprintf(pgstatBuf[bufc++],32,"%d",pgStatPmPipe[1]);
-	snprintf(pgstatBuf[bufc++],32,"%d",pgStatCollectorPmPipe[0]);
-	snprintf(pgstatBuf[bufc++],32,"%d",pgStatCollectorPmPipe[1]);
+	/* Pipe file ids (those not passed by write_backend_variables) */
 	snprintf(pgstatBuf[bufc++],32,"%d",pgStatPipe[0]);
 	snprintf(pgstatBuf[bufc++],32,"%d",pgStatPipe[1]);
 
@@ -493,14 +478,10 @@ pgstat_forkexec(STATS_PROCESS_TYPE procType)
 static void
 pgstat_parseArgs(int argc, char *argv[])
 {
-	Assert(argc == 10);
+	Assert(argc == 6);
 
 	argc = 3;
 	StrNCpy(postgres_exec_path,	argv[argc++], MAXPGPATH);
-	pgStatPmPipe[0]	= atoi(argv[argc++]);
-	pgStatPmPipe[1]	= atoi(argv[argc++]);
-	pgStatCollectorPmPipe[0] = atoi(argv[argc++]);
-	pgStatCollectorPmPipe[1] = atoi(argv[argc++]);
 	pgStatPipe[0]	= atoi(argv[argc++]);
 	pgStatPipe[1]	= atoi(argv[argc++]);
 }
@@ -592,8 +573,8 @@ pgstat_start(void)
 			/* Specific beos actions after backend startup */
 			beos_backend_startup();
 #endif
-			/* Close the postmaster's sockets, except for pgstat link */
-			ClosePostmasterPorts(false);
+			/* Close the postmaster's sockets */
+			ClosePostmasterPorts();
 
 			/* Drop our connection to postmaster's shared memory, as well */
 			PGSharedMemoryDetach();
@@ -632,31 +613,6 @@ pgstat_ispgstat(int pid)
 }
 
 
-/* ----------
- * pgstat_close_sockets() -
- *
- *	Called when postmaster forks a non-pgstat child process, to close off
- *	file descriptors that should not be held open in child processes.
- * ----------
- */
-void
-pgstat_close_sockets(void)
-{
-	if (pgStatPmPipe[0] >= 0)
-		closesocket(pgStatPmPipe[0]);
-	pgStatPmPipe[0] = -1;
-	if (pgStatPmPipe[1] >= 0)
-		closesocket(pgStatPmPipe[1]);
-	pgStatPmPipe[1] = -1;
-	if (pgStatCollectorPmPipe[0] >= 0)
-		closesocket(pgStatCollectorPmPipe[0]);
-	pgStatCollectorPmPipe[0] = -1;
-	if (pgStatCollectorPmPipe[1] >= 0)
-		closesocket(pgStatCollectorPmPipe[1]);
-	pgStatCollectorPmPipe[1] = -1;
-}
-
-
 /* ----------
  * pgstat_beterm() -
  *
@@ -1445,15 +1401,6 @@ PgstatBufferMain(int argc, char *argv[])
 	pgstat_parseArgs(argc,argv);
 #endif
 
-	/*
-	 * Close the writing end of the postmaster pipe, so we'll see it
-	 * closing when the postmaster terminates and can terminate as well.
-	 */
-	closesocket(pgStatPmPipe[1]);
-	pgStatPmPipe[1] = -1;
-	closesocket(pgStatCollectorPmPipe[1]);
-	pgStatCollectorPmPipe[1] = -1;
-
 	/*
 	 * Start a buffering process to read from the socket, so we have a
 	 * little more time to process incoming messages.
@@ -1517,7 +1464,6 @@ PgstatCollectorMain(int argc, char *argv[])
 	PgStat_Msg	msg;
 	fd_set		rfds;
 	int			readPipe;
-	int			pmPipe;
 	int			nready;
 	int			len = 0;
 	struct timeval timeout;
@@ -1555,7 +1501,6 @@ PgstatCollectorMain(int argc, char *argv[])
 	/* Close unwanted files */
 	closesocket(pgStatPipe[1]);
 	closesocket(pgStatSock);
-	pmPipe = pgStatCollectorPmPipe[0];
 
 	/*
 	 * Identify myself via ps
@@ -1823,17 +1768,9 @@ PgstatCollectorMain(int argc, char *argv[])
 	 * shutdown, we want to save the final stats to reuse at next startup.
 	 * But if the buffer process failed, it seems best not to (there may
 	 * even now be a new collector firing up, and we don't want it to read
-	 * a partially- rewritten stats file).	We can tell whether the
-	 * postmaster is still alive by checking to see if the postmaster pipe
-	 * is still open.  If it is read-ready (ie, EOF), the postmaster must
-	 * have quit.
-	 */
-	FD_ZERO(&rfds);
-	FD_SET(pmPipe, &rfds);
-	timeout.tv_sec = 0;
-	timeout.tv_usec = 0;
-	nready = select(pmPipe+1,&rfds,NULL,NULL,&timeout);
-	if (nready > 0 && FD_ISSET(pmPipe, &rfds)) 
+	 * a partially-rewritten stats file).
+	 */
+	if (!PostmasterIsAlive(false))
 		pgstat_write_statsfile();
 }
 
@@ -1852,8 +1789,8 @@ pgstat_recvbuffer(void)
 {
 	fd_set		rfds;
 	fd_set		wfds;
+	struct timeval timeout;
 	int			writePipe = pgStatPipe[1];
-	int			pmPipe = pgStatPmPipe[0];
 	int			maxfd;
 	int			nready;
 	int			len;
@@ -1937,8 +1874,7 @@ pgstat_recvbuffer(void)
 
 		/*
 		 * If we have messages to write out, we add the pipe to the write
-		 * descriptor set. Otherwise, we check if the postmaster might
-		 * have terminated.
+		 * descriptor set.
 		 */
 		if (msg_have > 0)
 		{
@@ -1946,17 +1882,16 @@ pgstat_recvbuffer(void)
 			if (writePipe > maxfd)
 				maxfd = writePipe;
 		}
-		else
-		{
-			FD_SET(pmPipe, &rfds);
-			if (pmPipe > maxfd)
-				maxfd = pmPipe;
-		}
 
 		/*
-		 * Wait for some work to do.
+		 * Wait for some work to do; but not for more than 10 seconds
+		 * (this determines how quickly we will shut down after postmaster
+		 * termination).
 		 */
-		nready = select(maxfd + 1, &rfds, &wfds, NULL, NULL);
+		timeout.tv_sec = 10;
+		timeout.tv_usec = 0;
+
+		nready = select(maxfd + 1, &rfds, &wfds, NULL, &timeout);
 		if (nready < 0)
 		{
 			if (errno == EINTR)
@@ -2062,11 +1997,9 @@ pgstat_recvbuffer(void)
 			continue;
 
 		/*
-		 * If the pipe from the postmaster is ready for reading, the
-		 * kernel must have closed it on exit() (the postmaster never
-		 * really writes to it). So we've done our job.
+		 * If the postmaster has terminated, we've done our job.
 		 */
-		if (FD_ISSET(pmPipe, &rfds))
+		if (!PostmasterIsAlive(true))
 			exit(0);
 	}
 }
diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index 89a22815098955fc0fcc5d5050bac3d087ff26bd..e7186c01b39b5f575189a463e5564bbee7ad4dd0 100644
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -37,14 +37,13 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/postmaster/postmaster.c,v 1.399 2004/05/28 15:14:03 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/postmaster/postmaster.c,v 1.400 2004/05/29 22:48:19 tgl Exp $
  *
  * NOTES
  *
  * Initialization:
- *		The Postmaster sets up a few shared memory data structures
- *		for the backends.  It should at the very least initialize the
- *		lock manager.
+ *		The Postmaster sets up shared memory data structures
+ *		for the backends.
  *
  * Synchronization:
  *		The Postmaster shares memory with the backends but should avoid
@@ -97,6 +96,7 @@
 #include "libpq/pqsignal.h"
 #include "miscadmin.h"
 #include "nodes/nodes.h"
+#include "postmaster/postmaster.h"
 #include "pgtime.h"
 #include "storage/fd.h"
 #include "storage/ipc.h"
@@ -113,22 +113,14 @@
 #include "pgstat.h"
 
 
-#ifdef HAVE_SIGPROCMASK
-sigset_t	UnBlockSig,
-			BlockSig,
-			AuthBlockSig;
-
-#else
-int			UnBlockSig,
-			BlockSig,
-			AuthBlockSig;
-#endif
-
 /*
  * List of active backends (or child processes anyway; we don't actually
  * know whether a given child has become a backend or is still in the
  * authorization phase).  This is used mainly to keep track of how many
  * children we have and send them appropriate signals when necessary.
+ *
+ * "Special" children such as the startup and bgwriter tasks are not in
+ * this list.
  */
 typedef struct bkend
 {
@@ -148,15 +140,6 @@ int			PostPortNumber;
 char	   *UnixSocketDir;
 char	   *ListenAddresses;
 
-/*
- * MaxBackends is the limit on the number of backends we can start.
- * Note that a larger MaxBackends value will increase the size of the
- * shared memory area as well as cause the postmaster to grab more
- * kernel semaphores, even if you never actually use that many
- * backends.
- */
-int			MaxBackends;
-
 /*
  * ReservedBackends is the number of backends reserved for superuser use.
  * This number is taken out of the pool size given by MaxBackends so
@@ -196,9 +179,6 @@ bool		SilentMode = false; /* silent mode (-S) */
 
 int			PreAuthDelay = 0;
 int			AuthenticationTimeout = 60;
-int			CheckPointTimeout = 300;
-int			CheckPointWarning = 30;
-time_t		LastSignalledCheckpoint = 0;
 
 bool		log_hostname;		/* for ps display and logging */
 bool		Log_connections = false;
@@ -209,13 +189,11 @@ char	   *rendezvous_name;
 /* list of library:init-function to be preloaded */
 char	   *preload_libraries_string = NULL;
 
-/* Startup/shutdown state */
+/* PIDs of special child processes; 0 when not running */
 static pid_t StartupPID = 0,
-			ShutdownPID = 0,
-			CheckPointPID = 0,
 			BgWriterPID = 0;
-static time_t checkpointed = 0;
 
+/* Startup/shutdown state */
 #define			NoShutdown		0
 #define			SmartShutdown	1
 #define			FastShutdown	2
@@ -232,7 +210,6 @@ bool		ClientAuthInProgress = false;		/* T during new-client
  * Also, the global MyCancelKey passes the cancel key assigned to a given
  * backend from the postmaster to that backend (via fork).
  */
-
 static unsigned int random_seed = 0;
 
 static int	debug_flag = 0;
@@ -263,6 +240,7 @@ static void reaper(SIGNAL_ARGS);
 static void sigusr1_handler(SIGNAL_ARGS);
 static void dummy_handler(SIGNAL_ARGS);
 static void CleanupProc(int pid, int exitstatus);
+static void HandleChildCrash(int pid, int exitstatus);
 static void LogChildExit(int lev, const char *procname,
 			 int pid, int exitstatus);
 static int	BackendRun(Port *port);
@@ -280,7 +258,7 @@ static void RandomSalt(char *cryptSalt, char *md5Salt);
 static void SignalChildren(int signal);
 static int	CountChildren(void);
 static bool CreateOptsFile(int argc, char *argv[], char *fullprogname);
-static pid_t SSDataBase(int xlop);
+static pid_t StartChildProcess(int xlop);
 static void
 postmaster_error(const char *fmt,...)
 /* This lets gcc check the format string for consistency. */
@@ -311,10 +289,8 @@ static void ShmemBackendArrayRemove(pid_t pid);
 
 #endif /* EXEC_BACKEND */
 
-#define StartupDataBase()		SSDataBase(BS_XLOG_STARTUP)
-#define CheckPointDataBase()	SSDataBase(BS_XLOG_CHECKPOINT)
-#define StartBackgroundWriter() SSDataBase(BS_XLOG_BGWRITER)
-#define ShutdownDataBase()		SSDataBase(BS_XLOG_SHUTDOWN)
+#define StartupDataBase()		StartChildProcess(BS_XLOG_STARTUP)
+#define StartBackgroundWriter() StartChildProcess(BS_XLOG_BGWRITER)
 
 
 /*
@@ -325,14 +301,13 @@ PostmasterMain(int argc, char *argv[])
 {
 	int			opt;
 	int			status;
-	char		original_extraoptions[MAXPGPATH];
 	char	   *potential_DataDir = NULL;
 	int			i;
 
-	*original_extraoptions = '\0';
-
 	progname = get_progname(argv[0]);
 
+	MyProcPid = PostmasterPid = getpid();
+
 	IsPostmasterEnvironment = true;
 
 	/*
@@ -359,8 +334,6 @@ PostmasterMain(int argc, char *argv[])
 	 */
 	umask((mode_t) 0077);
 
-	MyProcPid = PostmasterPid = getpid();
-
 	/*
 	 * Fire up essential subsystems: memory management
 	 */
@@ -470,12 +443,10 @@ PostmasterMain(int argc, char *argv[])
 			case 'o':
 
 				/*
-				 * Other options to pass to the backend on the command
-				 * line -- useful only for debugging.
+				 * Other options to pass to the backend on the command line
 				 */
 				strcat(ExtraOptions, " ");
 				strcat(ExtraOptions, optarg);
-				strcpy(original_extraoptions, optarg);
 				break;
 			case 'p':
 				SetConfigOption("port", optarg, PGC_POSTMASTER, PGC_S_ARGV);
@@ -656,7 +627,7 @@ PostmasterMain(int argc, char *argv[])
 	 * We want to do this before we try to grab the input sockets, because
 	 * the data directory interlock is more reliable than the socket-file
 	 * interlock (thanks to whoever decided to put socket files in /tmp
-	 * :-(). For the same reason, it's best to grab the TCP socket before
+	 * :-(). For the same reason, it's best to grab the TCP socket(s) before
 	 * the Unix socket.
 	 */
 	CreateDataDirLockFile(DataDir, true);
@@ -766,12 +737,13 @@ PostmasterMain(int argc, char *argv[])
 	BackendList = DLNewList();
 
 #ifdef WIN32
-
 	/*
-	 * Initialize the child pid/HANDLE arrays
+	 * Initialize the child pid/HANDLE arrays for signal handling.
 	 */
-	win32_childPIDArray = (pid_t *) malloc(NUM_BACKENDARRAY_ELEMS * sizeof(pid_t));
-	win32_childHNDArray = (HANDLE *) malloc(NUM_BACKENDARRAY_ELEMS * sizeof(HANDLE));
+	win32_childPIDArray = (pid_t *)
+		malloc(NUM_BACKENDARRAY_ELEMS * sizeof(pid_t));
+	win32_childHNDArray = (HANDLE *)
+		malloc(NUM_BACKENDARRAY_ELEMS * sizeof(HANDLE));
 	if (!win32_childPIDArray || !win32_childHNDArray)
 		ereport(FATAL,
 				(errcode(ERRCODE_OUT_OF_MEMORY),
@@ -791,16 +763,16 @@ PostmasterMain(int argc, char *argv[])
 	 *
 	 * CAUTION: when changing this list, check for side-effects on the signal
 	 * handling setup of child processes.  See tcop/postgres.c,
-	 * bootstrap/bootstrap.c, and postmaster/pgstat.c.
+	 * bootstrap/bootstrap.c, postmaster/bgwriter.c, and postmaster/pgstat.c.
 	 */
 	pqinitmask();
 	PG_SETMASK(&BlockSig);
 
 	pqsignal(SIGHUP, SIGHUP_handler);	/* reread config file and have
 										 * children do same */
-	pqsignal(SIGINT, pmdie);	/* send SIGTERM and ShutdownDataBase */
+	pqsignal(SIGINT, pmdie);	/* send SIGTERM and shut down */
 	pqsignal(SIGQUIT, pmdie);	/* send SIGQUIT and die */
-	pqsignal(SIGTERM, pmdie);	/* wait for children and ShutdownDataBase */
+	pqsignal(SIGTERM, pmdie);	/* wait for children and shut down */
 	pqsignal(SIGALRM, SIG_IGN); /* ignored */
 	pqsignal(SIGPIPE, SIG_IGN); /* ignored */
 	pqsignal(SIGUSR1, sigusr1_handler); /* message from child process */
@@ -822,19 +794,6 @@ PostmasterMain(int argc, char *argv[])
 	 */
 	whereToSendOutput = None;
 
-	/*
-	 * On many platforms, the first call of localtime() incurs significant
-	 * overhead to load timezone info from the system configuration files.
-	 * By doing it once in the postmaster, we avoid having to do it in
-	 * every started child process.  The savings are not huge, but they
-	 * add up...
-	 */
-	{
-		time_t		now = time(NULL);
-
-		(void) pg_localtime(&now);
-	}
-
 	/*
 	 * Initialize and try to startup the statistics collector process
 	 */
@@ -956,10 +915,7 @@ reg_reply(DNSServiceRegistrationReplyErrorType errorCode, void *context)
 static void
 pmdaemonize(void)
 {
-#ifdef WIN32
-	/* not supported */
-	elog(FATAL, "SilentMode not supported under WIN32");
-#else
+#ifndef WIN32
 	int			i;
 	pid_t		pid;
 
@@ -989,7 +945,7 @@ pmdaemonize(void)
 	setitimer(ITIMER_PROF, &prof_itimer, NULL);
 #endif
 
-	MyProcPid = getpid();		/* reset MyProcPid to child */
+	MyProcPid = PostmasterPid = getpid();	/* reset PID vars to child */
 
 /* GH: If there's no setsid(), we hopefully don't need silent mode.
  * Until there's a better solution.
@@ -1007,7 +963,10 @@ pmdaemonize(void)
 	dup2(i, 1);
 	dup2(i, 2);
 	close(i);
-#endif
+#else  /* WIN32 */
+	/* not supported */
+	elog(FATAL, "SilentMode not supported under WIN32");
+#endif /* WIN32 */
 }
 
 
@@ -1053,19 +1012,21 @@ usage(const char *progname)
 
 
 /*
- * Main loop of postmaster
+ * Main idle loop of postmaster
  */
 static int
 ServerLoop(void)
 {
 	fd_set		readmask;
 	int			nSockets;
-	struct timeval now,
+	time_t		now,
+				last_touch_time;
+	struct timeval earlier,
 				later;
 	struct timezone tz;
-	int			i;
 
-	gettimeofday(&now, &tz);
+	gettimeofday(&earlier, &tz);
+	last_touch_time = time(NULL);
 
 	nSockets = initMasks(&readmask);
 
@@ -1074,70 +1035,32 @@ ServerLoop(void)
 		Port	   *port;
 		fd_set		rmask;
 		struct timeval timeout;
+		int			selres;
+		int			i;
 
 		/*
-		 * The timeout for the select() below is normally set on the basis
-		 * of the time to the next checkpoint.	However, if for some
-		 * reason we don't have a next-checkpoint time, time out after 60
-		 * seconds. This keeps checkpoint scheduling from locking up when
-		 * we get new connection requests infrequently (since we are
-		 * likely to detect checkpoint completion just after enabling
-		 * signals below, after we've already made the decision about how
-		 * long to wait this time).
+		 * Wait for something to happen.
+		 *
+		 * We wait at most one minute, to ensure that the other background
+		 * tasks handled below get done even when no requests are arriving.
 		 */
+		memcpy((char *) &rmask, (char *) &readmask, sizeof(fd_set));
+
 		timeout.tv_sec = 60;
 		timeout.tv_usec = 0;
 
-		if (CheckPointPID == 0 && checkpointed &&
-			StartupPID == 0 && Shutdown == NoShutdown &&
-			!FatalError && random_seed != 0)
-		{
-			time_t		now = time(NULL);
-
-			if (CheckPointTimeout + checkpointed > now)
-			{
-				/*
-				 * Not time for checkpoint yet, so set select timeout
-				 */
-				timeout.tv_sec = CheckPointTimeout + checkpointed - now;
-			}
-			else
-			{
-				/* Time to make the checkpoint... */
-				CheckPointPID = CheckPointDataBase();
-
-				/*
-				 * if fork failed, schedule another try at 0.1 normal
-				 * delay
-				 */
-				if (CheckPointPID == 0)
-				{
-					timeout.tv_sec = CheckPointTimeout / 10;
-					checkpointed = now + timeout.tv_sec - CheckPointTimeout;
-				}
-			}
-		}
+		PG_SETMASK(&UnBlockSig);
 
-		/*
-		 * If no background writer process is running and we should do
-		 * background writing, start one. It doesn't matter if this fails,
-		 * we'll just try again later.
-		 */
-		if (BgWriterPID == 0 && BgWriterPercent > 0 &&
-			StartupPID == 0 && Shutdown == NoShutdown &&
-			!FatalError && random_seed != 0)
-			BgWriterPID = StartBackgroundWriter();
+		selres = select(nSockets, &rmask, NULL, NULL, &timeout);
 
 		/*
-		 * Wait for something to happen.
+		 * Block all signals until we wait again.  (This makes it safe for
+		 * our signal handlers to do nontrivial work.)
 		 */
-		memcpy((char *) &rmask, (char *) &readmask, sizeof(fd_set));
-
-		PG_SETMASK(&UnBlockSig);
+		PG_SETMASK(&BlockSig);
 
-		if (select(nSockets, &rmask, NULL, NULL, &timeout) < 0)
+		if (selres < 0)
 		{
-			PG_SETMASK(&BlockSig);
 			if (errno == EINTR || errno == EWOULDBLOCK)
 				continue;
 			ereport(LOG,
@@ -1147,63 +1070,85 @@ ServerLoop(void)
 		}
 
 		/*
-		 * Block all signals until we wait again.  (This makes it safe for
-		 * our signal handlers to do nontrivial work.)
-		 */
-		PG_SETMASK(&BlockSig);
-
-		/*
-		 * Select a random seed at the time of first receiving a request.
+		 * New connection pending on any of our sockets? If so, fork a
+		 * child process to deal with it.
 		 */
-		while (random_seed == 0)
+		if (selres > 0)
 		{
-			gettimeofday(&later, &tz);
-
 			/*
-			 * We are not sure how much precision is in tv_usec, so we
-			 * swap the nibbles of 'later' and XOR them with 'now'. On the
-			 * off chance that the result is 0, we loop until it isn't.
+			 * Select a random seed at the time of first receiving a request.
 			 */
-			random_seed = now.tv_usec ^
-				((later.tv_usec << 16) |
-				 ((later.tv_usec >> 16) & 0xffff));
-		}
+			while (random_seed == 0)
+			{
+				gettimeofday(&later, &tz);
 
-		/*
-		 * New connection pending on any of our sockets? If so, fork a
-		 * child process to deal with it.
-		 */
-		for (i = 0; i < MAXLISTEN; i++)
-		{
-			if (ListenSocket[i] == -1)
-				break;
-			if (FD_ISSET(ListenSocket[i], &rmask))
+				/*
+				 * We are not sure how much precision is in tv_usec, so we
+				 * swap the nibbles of 'later' and XOR them with 'earlier'. On
+				 * the off chance that the result is 0, we loop until it isn't.
+				 */
+				random_seed = earlier.tv_usec ^
+					((later.tv_usec << 16) |
+					 ((later.tv_usec >> 16) & 0xffff));
+			}
+
+			for (i = 0; i < MAXLISTEN; i++)
 			{
-				port = ConnCreate(ListenSocket[i]);
-				if (port)
+				if (ListenSocket[i] == -1)
+					break;
+				if (FD_ISSET(ListenSocket[i], &rmask))
 				{
-					BackendStartup(port);
-
-					/*
-					 * We no longer need the open socket or port structure
-					 * in this process
-					 */
-					StreamClose(port->sock);
-					ConnFree(port);
+					port = ConnCreate(ListenSocket[i]);
+					if (port)
+					{
+						BackendStartup(port);
+
+						/*
+						 * We no longer need the open socket or port structure
+						 * in this process
+						 */
+						StreamClose(port->sock);
+						ConnFree(port);
+					}
 				}
 			}
 		}
 
+		/*
+		 * If no background writer process is running, and we are not in
+		 * a state that prevents it, start one.  It doesn't matter if this
+		 * fails, we'll just try again later.
+		 */
+		if (BgWriterPID == 0 && StartupPID == 0 && !FatalError)
+		{
+			BgWriterPID = StartBackgroundWriter();
+			/* If shutdown is pending, set it going */
+			if (Shutdown > NoShutdown && BgWriterPID != 0)
+				kill(BgWriterPID, SIGUSR2);
+		}
+
 		/* If we have lost the stats collector, try to start a new one */
 		if (!pgstat_is_running)
 			pgstat_start();
+
+		/*
+		 * Touch the socket and lock file at least every ten minutes, to ensure
+		 * that they are not removed by overzealous /tmp-cleaning tasks.
+		 */
+		now = time(NULL);
+		if (now - last_touch_time >= 10 * 60)
+		{
+			TouchSocketFile();
+			TouchSocketLockFile();
+			last_touch_time = now;
+		}
 	}
 }
 
 
 /*
- * Initialise the masks for select() for the ports
- * we are listening on.  Return the number of sockets to listen on.
+ * Initialise the masks for select() for the ports we are listening on.
+ * Return the number of sockets to listen on.
  */
 static int
 initMasks(fd_set *rmask)
@@ -1543,14 +1488,7 @@ processCancelRequest(Port *port, void *pkt)
 	backendPID = (int) ntohl(canc->backendPID);
 	cancelAuthCode = (long) ntohl(canc->cancelAuthCode);
 
-	if (backendPID == CheckPointPID)
-	{
-		ereport(DEBUG2,
-				(errmsg_internal("ignoring cancel request for checkpoint process %d",
-								 backendPID)));
-		return;
-	}
-	else if (backendPID == BgWriterPID)
+	if (backendPID == BgWriterPID)
 	{
 		ereport(DEBUG2,
 				(errmsg_internal("ignoring cancel request for bgwriter process %d",
@@ -1561,7 +1499,7 @@ processCancelRequest(Port *port, void *pkt)
 	/*
 	 * See if we have a matching backend.  In the EXEC_BACKEND case, we
 	 * can no longer access the postmaster's own backend list, and must
-	 * rely on the backup array in shared memory.
+	 * rely on the duplicate array in shared memory.
 	 */
 #ifndef EXEC_BACKEND
 	for (curr = DLGetHead(BackendList); curr; curr = DLGetSucc(curr))
@@ -1687,7 +1625,7 @@ ConnFree(Port *conn)
  * them open, of course.
  */
 void
-ClosePostmasterPorts(bool pgstat_too)
+ClosePostmasterPorts(void)
 {
 	int			i;
 
@@ -1700,10 +1638,6 @@ ClosePostmasterPorts(bool pgstat_too)
 			ListenSocket[i] = -1;
 		}
 	}
-
-	/* Close pgstat control sockets, unless we're starting pgstat itself */
-	if (pgstat_too)
-		pgstat_close_sockets();
 }
 
 
@@ -1741,6 +1675,8 @@ SIGHUP_handler(SIGNAL_ARGS)
 			 (errmsg("received SIGHUP, reloading configuration files")));
 		ProcessConfigFile(PGC_SIGHUP);
 		SignalChildren(SIGHUP);
+		if (BgWriterPID != 0)
+			kill(BgWriterPID, SIGHUP);
 		load_hba();
 		load_ident();
 
@@ -1748,13 +1684,6 @@ SIGHUP_handler(SIGNAL_ARGS)
 		/* Update the starting-point file for future children */
 		write_nondefault_variables(PGC_SIGHUP);
 #endif
-
-		/*
-		 * Tell the background writer to terminate so that we will start a
-		 * new one with a possibly changed config
-		 */
-		if (BgWriterPID != 0)
-			kill(BgWriterPID, SIGTERM);
 	}
 
 	PG_SETMASK(&UnBlockSig);
@@ -1780,11 +1709,10 @@ pmdie(SIGNAL_ARGS)
 	switch (postgres_signal_arg)
 	{
 		case SIGTERM:
-
 			/*
 			 * Smart Shutdown:
 			 *
-			 * Wait for children to end their work and ShutdownDataBase.
+			 * Wait for children to end their work, then shut down.
 			 */
 			if (Shutdown >= SmartShutdown)
 				break;
@@ -1792,36 +1720,28 @@ pmdie(SIGNAL_ARGS)
 			ereport(LOG,
 					(errmsg("received smart shutdown request")));
 
-			/* Must tell bgwriter to quit, or it never will... */
-			if (BgWriterPID != 0)
-				kill(BgWriterPID, SIGTERM);
-
-			if (DLGetHead(BackendList)) /* let reaper() handle this */
-				break;
+			if (DLGetHead(BackendList))
+				break;			/* let reaper() handle this */
 
 			/*
-			 * No children left. Shutdown data base system.
+			 * No children left. Begin shutdown of data base system.
 			 */
-			if (StartupPID > 0 || FatalError)	/* let reaper() handle
-												 * this */
-				break;
-			if (ShutdownPID > 0)
-			{
-				elog(PANIC, "shutdown process %d already running",
-					 (int) ShutdownPID);
-				abort();
-			}
-
-			ShutdownPID = ShutdownDataBase();
+			if (StartupPID != 0 || FatalError)
+				break;			/* let reaper() handle this */
+			/* Start the bgwriter if not running */
+			if (BgWriterPID == 0)
+				BgWriterPID = StartBackgroundWriter();
+			/* And tell it to shut down */
+			if (BgWriterPID != 0)
+				kill(BgWriterPID, SIGUSR2);
 			break;
 
 		case SIGINT:
-
 			/*
 			 * Fast Shutdown:
 			 *
 			 * Abort all children with SIGTERM (rollback active transactions
-			 * and exit) and ShutdownDataBase when they are gone.
+			 * and exit) and shut down when they are gone.
 			 */
 			if (Shutdown >= FastShutdown)
 				break;
@@ -1842,33 +1762,34 @@ pmdie(SIGNAL_ARGS)
 			}
 
 			/*
-			 * No children left. Shutdown data base system.
+			 * No children left. Begin shutdown of data base system.
 			 *
-			 * Unlike the previous case, it is not an error for the shutdown
-			 * process to be running already (we could get SIGTERM
-			 * followed shortly later by SIGINT).
+			 * Note: if we previously got SIGTERM then we may send SIGUSR2
+			 * to the bgwriter a second time here.  This should be harmless.
 			 */
-			if (StartupPID > 0 || FatalError)	/* let reaper() handle
-												 * this */
-				break;
-			if (ShutdownPID == 0)
-				ShutdownPID = ShutdownDataBase();
+			if (StartupPID != 0 || FatalError)
+				break;			/* let reaper() handle this */
+			/* Start the bgwriter if not running */
+			if (BgWriterPID == 0)
+				BgWriterPID = StartBackgroundWriter();
+			/* And tell it to shut down */
+			if (BgWriterPID != 0)
+				kill(BgWriterPID, SIGUSR2);
 			break;
 
 		case SIGQUIT:
-
 			/*
 			 * Immediate Shutdown:
 			 *
 			 * abort all children with SIGQUIT and exit without attempt to
-			 * properly shutdown data base system.
+			 * properly shut down data base system.
 			 */
 			ereport(LOG,
 					(errmsg("received immediate shutdown request")));
-			if (ShutdownPID > 0)
-				kill(ShutdownPID, SIGQUIT);
-			if (StartupPID > 0)
+			if (StartupPID != 0)
 				kill(StartupPID, SIGQUIT);
+			if (BgWriterPID != 0)
+				kill(BgWriterPID, SIGQUIT);
 			if (DLGetHead(BackendList))
 				SignalChildren(SIGQUIT);
 			ExitPostmaster(0);
@@ -1939,22 +1860,11 @@ reaper(SIGNAL_ARGS)
 		}
 
 		/*
-		 * Check if this child was a shutdown or startup process.
+		 * Check if this child was a startup process.
 		 */
-		if (ShutdownPID > 0 && pid == ShutdownPID)
-		{
-			if (exitstatus != 0)
-			{
-				LogChildExit(LOG, gettext("shutdown process"),
-							 pid, exitstatus);
-				ExitPostmaster(1);
-			}
-			/* Normal postmaster exit is here */
-			ExitPostmaster(0);
-		}
-
-		if (StartupPID > 0 && pid == StartupPID)
+		if (StartupPID != 0 && pid == StartupPID)
 		{
+			StartupPID = 0;
 			if (exitstatus != 0)
 			{
 				LogChildExit(LOG, gettext("startup process"),
@@ -1963,7 +1873,6 @@ reaper(SIGNAL_ARGS)
 						(errmsg("aborting startup due to startup process failure")));
 				ExitPostmaster(1);
 			}
-			StartupPID = 0;
 
 			/*
 			 * Startup succeeded - we are done with system startup or recovery.
@@ -1971,33 +1880,51 @@ reaper(SIGNAL_ARGS)
 			FatalError = false;
 
 			/*
-			 * Arrange for first checkpoint to occur after standard delay.
+			 * Crank up the background writer.  It doesn't matter if this
+			 * fails, we'll just try again later.
 			 */
-			CheckPointPID = 0;
-			checkpointed = time(NULL);
+			Assert(BgWriterPID == 0);
+			BgWriterPID = StartBackgroundWriter();
 
 			/*
 			 * Go to shutdown mode if a shutdown request was pending.
 			 */
-			if (Shutdown > NoShutdown)
+			if (Shutdown > NoShutdown && BgWriterPID != 0)
+				kill(BgWriterPID, SIGUSR2);
+
+			continue;
+		}
+
+		/*
+		 * Was it the bgwriter?
+		 */
+		if (BgWriterPID != 0 && pid == BgWriterPID)
+		{
+			if (exitstatus == 0 && Shutdown > NoShutdown &&
+				!FatalError && !DLGetHead(BackendList))
 			{
-				if (ShutdownPID > 0)
-				{
-					elog(PANIC, "startup process %d died while shutdown process %d already running",
-						 pid, (int) ShutdownPID);
-					abort();
-				}
-				ShutdownPID = ShutdownDataBase();
+				/*
+				 * Normal postmaster exit is here: we've seen normal
+				 * exit of the bgwriter after it's been told to shut down.
+				 * We expect that it wrote a shutdown checkpoint.  (If
+				 * for some reason it didn't, recovery will occur on next
+				 * postmaster start.)
+				 */
+				ExitPostmaster(0);
 			}
-
-			goto reaper_done;
+			/*
+			 * Any unexpected exit of the bgwriter is treated as a crash.
+			 */
+			LogChildExit(DEBUG2, gettext("background writer process"),
+						 pid, exitstatus);
+			HandleChildCrash(pid, exitstatus);
+			continue;
 		}
 
 		/*
-		 * Else do standard child cleanup.
+		 * Else do standard backend child cleanup.
 		 */
 		CleanupProc(pid, exitstatus);
-
 	}							/* loop over pending child-death reports */
 
 	if (FatalError)
@@ -2006,7 +1933,7 @@ reaper(SIGNAL_ARGS)
 		 * Wait for all children exit, then reset shmem and
 		 * StartupDataBase.
 		 */
-		if (DLGetHead(BackendList) || StartupPID > 0 || ShutdownPID > 0)
+		if (DLGetHead(BackendList) || StartupPID != 0 || BgWriterPID != 0)
 			goto reaper_done;
 		ereport(LOG,
 			(errmsg("all server processes terminated; reinitializing")));
@@ -2021,11 +1948,14 @@ reaper(SIGNAL_ARGS)
 
 	if (Shutdown > NoShutdown)
 	{
-		if (DLGetHead(BackendList))
-			goto reaper_done;
-		if (StartupPID > 0 || ShutdownPID > 0)
+		if (DLGetHead(BackendList) || StartupPID != 0)
 			goto reaper_done;
-		ShutdownPID = ShutdownDataBase();
+		/* Start the bgwriter if not running */
+		if (BgWriterPID == 0)
+			BgWriterPID = StartBackgroundWriter();
+		/* And tell it to shut down */
+		if (BgWriterPID != 0)
+			kill(BgWriterPID, SIGUSR2);
 	}
 
 reaper_done:
@@ -2044,11 +1974,9 @@ static void
 CleanupProc(int pid,
 			int exitstatus)		/* child's exit status. */
 {
-	Dlelem	   *curr,
-			   *next;
-	Backend    *bp;
+	Dlelem	   *curr;
 
-	LogChildExit(DEBUG2, gettext("child process"), pid, exitstatus);
+	LogChildExit(DEBUG2, gettext("server process"), pid, exitstatus);
 
 	/*
 	 * If a backend dies in an ugly way (i.e. exit status not 0) then we
@@ -2056,61 +1984,81 @@ CleanupProc(int pid,
 	 * we assume everything is hunky dory and simply remove the backend
 	 * from the active backend list.
 	 */
-	if (exitstatus == 0)
+	if (exitstatus != 0)
+	{
+		HandleChildCrash(pid, exitstatus);
+		return;
+	}
+
+	for (curr = DLGetHead(BackendList); curr; curr = DLGetSucc(curr))
 	{
-		curr = DLGetHead(BackendList);
-		while (curr)
+		Backend    *bp = (Backend *) DLE_VAL(curr);
+
+		if (bp->pid == pid)
 		{
-			bp = (Backend *) DLE_VAL(curr);
-			if (bp->pid == pid)
-			{
+			DLRemove(curr);
+			free(bp);
+			DLFreeElem(curr);
 #ifdef EXEC_BACKEND
-				ShmemBackendArrayRemove(bp->pid);
+			ShmemBackendArrayRemove(pid);
 #endif
-				DLRemove(curr);
-				free(bp);
-				DLFreeElem(curr);
-				break;
-			}
-			curr = DLGetSucc(curr);
-		}
-
-		if (pid == CheckPointPID)
-		{
-			CheckPointPID = 0;
-			if (!FatalError)
-			{
-				checkpointed = time(NULL);
-			}
-		}
-		else if (pid == BgWriterPID)
-			BgWriterPID = 0;
-		else
+			/* Tell the collector about backend termination */
 			pgstat_beterm(pid);
-
-		return;
+			break;
+		}
 	}
+}
 
-	/* below here we're dealing with a non-normal exit */
+/*
+ * HandleChildCrash -- cleanup after failed backend or bgwriter.
+ *
+ * The objectives here are to clean up our local state about the child
+ * process, and to signal all other remaining children to quickdie.
+ */
+static void
+HandleChildCrash(int pid,
+				 int exitstatus) /* child's exit status. */
+{
+	Dlelem	   *curr,
+			   *next;
+	Backend    *bp;
 
-	/* Make log entry unless we did so already */
+	/*
+	 * Make log entry unless there was a previous crash (if so, nonzero
+	 * exit status is to be expected in SIGQUIT response; don't clutter log)
+	 */
 	if (!FatalError)
 	{
 		LogChildExit(LOG,
-				 (pid == CheckPointPID) ? gettext("checkpoint process") :
-					 (pid == BgWriterPID) ? gettext("bgwriter process") :
+					 (pid == BgWriterPID) ?
+					 gettext("background writer process") :
 					 gettext("server process"),
 					 pid, exitstatus);
 		ereport(LOG,
-			  (errmsg("terminating any other active server processes")));
+				(errmsg("terminating any other active server processes")));
 	}
 
-	curr = DLGetHead(BackendList);
-	while (curr)
+	/* Process regular backends */
+	for (curr = DLGetHead(BackendList); curr; curr = next)
 	{
 		next = DLGetSucc(curr);
 		bp = (Backend *) DLE_VAL(curr);
-		if (bp->pid != pid)
+		if (bp->pid == pid)
+		{
+			/*
+			 * Found entry for freshly-dead backend, so remove it.
+			 */
+			DLRemove(curr);
+			free(bp);
+			DLFreeElem(curr);
+#ifdef EXEC_BACKEND
+			ShmemBackendArrayRemove(pid);
+#endif
+			/* Tell the collector about backend termination */
+			pgstat_beterm(pid);
+			/* Keep looping so we can signal remaining backends */
+		}
+		else
 		{
 			/*
 			 * This backend is still alive.  Unless we did so already,
@@ -2130,34 +2078,18 @@ CleanupProc(int pid,
 				kill(bp->pid, (SendStop ? SIGSTOP : SIGQUIT));
 			}
 		}
-		else
-		{
-			/*
-			 * Found entry for freshly-dead backend, so remove it.
-			 */
-#ifdef EXEC_BACKEND
-			ShmemBackendArrayRemove(bp->pid);
-#endif
-			DLRemove(curr);
-			free(bp);
-			DLFreeElem(curr);
-		}
-		curr = next;
 	}
 
-	if (pid == CheckPointPID)
-	{
-		CheckPointPID = 0;
-		checkpointed = 0;
-	}
-	else if (pid == BgWriterPID)
+	/* Take care of the bgwriter too */
+	if (pid == BgWriterPID)
 		BgWriterPID = 0;
-	else
+	else if (BgWriterPID != 0 && !FatalError)
 	{
-		/*
-		 * Tell the collector about backend termination
-		 */
-		pgstat_beterm(pid);
+		ereport(DEBUG2,
+				(errmsg_internal("sending %s to process %d",
+								 (SendStop ? "SIGSTOP" : "SIGQUIT"),
+								 (int) BgWriterPID)));
+		kill(BgWriterPID, (SendStop ? SIGSTOP : SIGQUIT));
 	}
 
 	FatalError = true;
@@ -2204,26 +2136,16 @@ LogChildExit(int lev, const char *procname, int pid, int exitstatus)
 static void
 SignalChildren(int signal)
 {
-	Dlelem	   *curr,
-			   *next;
-	Backend    *bp;
+	Dlelem	   *curr;
 
-	curr = DLGetHead(BackendList);
-	while (curr)
+	for (curr = DLGetHead(BackendList); curr; curr = DLGetSucc(curr))
 	{
-		next = DLGetSucc(curr);
-		bp = (Backend *) DLE_VAL(curr);
+		Backend    *bp = (Backend *) DLE_VAL(curr);
 
-		if (bp->pid != MyProcPid)
-		{
-			ereport(DEBUG2,
-					(errmsg_internal("sending signal %d to process %d",
-									 signal,
-									 (int) bp->pid)));
-			kill(bp->pid, signal);
-		}
-
-		curr = next;
+		ereport(DEBUG4,
+				(errmsg_internal("sending signal %d to process %d",
+								 signal, (int) bp->pid)));
+		kill(bp->pid, signal);
 	}
 }
 
@@ -2346,10 +2268,10 @@ BackendStartup(Port *port)
 	 */
 	bn->pid = pid;
 	bn->cancel_key = MyCancelKey;
+	DLAddHead(BackendList, DLNewElem(bn));
 #ifdef EXEC_BACKEND
 	ShmemBackendArrayAdd(bn);
 #endif
-	DLAddHead(BackendList, DLNewElem(bn));
 
 	return STATUS_OK;
 }
@@ -2438,9 +2360,9 @@ BackendRun(Port *port)
 
 	/*
 	 * Let's clean up ourselves as the postmaster child, and close the
-	 * postmaster's other sockets
+	 * postmaster's listen sockets
 	 */
-	ClosePostmasterPorts(true);
+	ClosePostmasterPorts();
 
 	/* We don't want the postmaster's proc_exit() handlers */
 	on_exit_reset();
@@ -2833,23 +2755,23 @@ SubPostmasterMain(int argc, char *argv[])
 	if (strcmp(argv[1], "-forkboot") == 0)
 	{
 		/* Close the postmaster's sockets */
-		ClosePostmasterPorts(true);
+		ClosePostmasterPorts();
 
 		/* Attach process to shared segments */
 		CreateSharedMemoryAndSemaphores(false, MaxBackends, 0);
 
 		BootstrapMain(argc - 2, argv + 2);
-		ExitPostmaster(0);
+		proc_exit(0);
 	}
 	if (strcmp(argv[1], "-forkbuf") == 0)
 	{
 		/* Close the postmaster's sockets */
-		ClosePostmasterPorts(false);
+		ClosePostmasterPorts();
 
 		/* Do not want to attach to shared memory */
 
 		PgstatBufferMain(argc, argv);
-		ExitPostmaster(0);
+		proc_exit(0);
 	}
 	if (strcmp(argv[1], "-forkcol") == 0)
 	{
@@ -2861,7 +2783,7 @@ SubPostmasterMain(int argc, char *argv[])
 		/* Do not want to attach to shared memory */
 
 		PgstatCollectorMain(argc, argv);
-		ExitPostmaster(0);
+		proc_exit(0);
 	}
 
 	return 1;					/* shouldn't get here */
@@ -2886,8 +2808,6 @@ ExitPostmaster(int status)
 	 *
 	 * MUST		-- vadim 05-10-1999
 	 */
-	/* Should I use true instead? */
-	ClosePostmasterPorts(false);
 
 	proc_exit(status);
 }
@@ -2902,45 +2822,6 @@ sigusr1_handler(SIGNAL_ARGS)
 
 	PG_SETMASK(&BlockSig);
 
-	if (CheckPostmasterSignal(PMSIGNAL_DO_CHECKPOINT))
-	{
-		if (CheckPointWarning != 0)
-		{
-			/*
-			 * This only times checkpoints forced by running out of
-			 * segment files.  Other checkpoints could reduce the
-			 * frequency of forced checkpoints.
-			 */
-			time_t		now = time(NULL);
-
-			if (LastSignalledCheckpoint != 0)
-			{
-				int			elapsed_secs = now - LastSignalledCheckpoint;
-
-				if (elapsed_secs < CheckPointWarning)
-					ereport(LOG,
-							(errmsg("checkpoints are occurring too frequently (%d seconds apart)",
-									elapsed_secs),
-							 errhint("Consider increasing the configuration parameter \"checkpoint_segments\".")));
-			}
-			LastSignalledCheckpoint = now;
-		}
-
-		/*
-		 * Request to schedule a checkpoint
-		 *
-		 * Ignore request if checkpoint is already running or checkpointing
-		 * is currently disabled
-		 */
-		if (CheckPointPID == 0 && checkpointed &&
-			StartupPID == 0 && Shutdown == NoShutdown &&
-			!FatalError && random_seed != 0)
-		{
-			CheckPointPID = CheckPointDataBase();
-			/* note: if fork fails, CheckPointPID stays 0; nothing happens */
-		}
-	}
-
 	if (CheckPostmasterSignal(PMSIGNAL_PASSWORD_CHANGE))
 	{
 		/*
@@ -2957,7 +2838,7 @@ sigusr1_handler(SIGNAL_ARGS)
 		 * CatchupInterruptHandler). See storage/ipc/sinval[adt].c for the
 		 * use of this.
 		 */
-		if (Shutdown == NoShutdown)
+		if (Shutdown <= SmartShutdown)
 			SignalChildren(SIGUSR1);
 	}
 
@@ -2971,9 +2852,10 @@ sigusr1_handler(SIGNAL_ARGS)
  * Dummy signal handler
  *
  * We use this for signals that we don't actually use in the postmaster,
- * but we do use in backends.  If we SIG_IGN such signals in the postmaster,
- * then a newly started backend might drop a signal that arrives before it's
- * able to reconfigure its signal processing.  (See notes in postgres.c.)
+ * but we do use in backends.  If we were to SIG_IGN such signals in the
+ * postmaster, then a newly started backend might drop a signal that arrives
+ * before it's able to reconfigure its signal processing.  (See notes in
+ * tcop/postgres.c.)
  */
 static void
 dummy_handler(SIGNAL_ARGS)
@@ -3057,37 +2939,28 @@ static int
 CountChildren(void)
 {
 	Dlelem	   *curr;
-	Backend    *bp;
 	int			cnt = 0;
 
 	for (curr = DLGetHead(BackendList); curr; curr = DLGetSucc(curr))
 	{
-		bp = (Backend *) DLE_VAL(curr);
-		if (bp->pid != MyProcPid)
-			cnt++;
-	}
-	/* Checkpoint and bgwriter will be in the list, discount them */
-	if (CheckPointPID != 0)
-		cnt--;
-	if (BgWriterPID != 0)
-		cnt--;
+		cnt++;
+	}
 	return cnt;
 }
 
 
 /*
- * SSDataBase -- start a non-backend child process for the postmaster
+ * StartChildProcess -- start a non-backend child process for the postmaster
  *
  * xlog determines what kind of child will be started.  All child types
  * initially go to BootstrapMain, which will handle common setup.
  *
- * Return value of SSDataBase is subprocess' PID, or 0 if failed to start
- * subprocess (0 is returned only for checkpoint/bgwriter cases).
+ * Return value of StartChildProcess is subprocess' PID, or 0 if failed
+ * to start subprocess.
  */
 static pid_t
-SSDataBase(int xlop)
+StartChildProcess(int xlop)
 {
-	Backend    *bn;
 	pid_t		pid;
 	char	   *av[10];
 	int			ac = 0;
@@ -3153,7 +3026,7 @@ SSDataBase(int xlop)
 		IsUnderPostmaster = true;	/* we are a postmaster subprocess now */
 
 		/* Close the postmaster's sockets */
-		ClosePostmasterPorts(true);
+		ClosePostmasterPorts();
 
 		/* Lose the postmaster's on-exit routines and port connections */
 		on_exit_reset();
@@ -3180,17 +3053,9 @@ SSDataBase(int xlop)
 				ereport(LOG,
 						(errmsg("could not fork startup process: %m")));
 				break;
-			case BS_XLOG_CHECKPOINT:
-				ereport(LOG,
-					  (errmsg("could not fork checkpoint process: %m")));
-				break;
 			case BS_XLOG_BGWRITER:
 				ereport(LOG,
-						(errmsg("could not fork bgwriter process: %m")));
-				break;
-			case BS_XLOG_SHUTDOWN:
-				ereport(LOG,
-						(errmsg("could not fork shutdown process: %m")));
+						(errmsg("could not fork background writer process: %m")));
 				break;
 			default:
 				ereport(LOG,
@@ -3199,50 +3064,17 @@ SSDataBase(int xlop)
 		}
 
 		/*
-		 * fork failure is fatal during startup/shutdown, but there's no
-		 * need to choke if a routine checkpoint or starting a background
-		 * writer fails.
+		 * fork failure is fatal during startup, but there's no need
+		 * to choke immediately if starting other child types fails.
 		 */
-		if (xlop == BS_XLOG_CHECKPOINT)
-			return 0;
-		if (xlop == BS_XLOG_BGWRITER)
-			return 0;
-		ExitPostmaster(1);
+		if (xlop == BS_XLOG_STARTUP)
+			ExitPostmaster(1);
+		return 0;
 	}
 
 	/*
 	 * in parent, successful fork
-	 *
-	 * The startup and shutdown processes are not considered normal
-	 * backends, but the checkpoint and bgwriter processes are. They must
-	 * be added to the list of backends.
 	 */
-	if (xlop == BS_XLOG_CHECKPOINT || xlop == BS_XLOG_BGWRITER)
-	{
-		if (!(bn = (Backend *) malloc(sizeof(Backend))))
-		{
-			ereport(LOG,
-					(errcode(ERRCODE_OUT_OF_MEMORY),
-					 errmsg("out of memory")));
-			ExitPostmaster(1);
-		}
-
-		bn->pid = pid;
-		bn->cancel_key = PostmasterRandom();
-#ifdef EXEC_BACKEND
-		ShmemBackendArrayAdd(bn);
-#endif
-		DLAddHead(BackendList, DLNewElem(bn));
-
-		/*
-		 * Since this code is executed periodically, it's a fine place to
-		 * do other actions that should happen every now and then on no
-		 * particular schedule.  Such as...
-		 */
-		TouchSocketFile();
-		TouchSocketLockFile();
-	}
-
 	return pid;
 }
 
@@ -3316,6 +3148,8 @@ extern int	pgStatSock;
 
 #define write_var(var,fp) fwrite((void*)&(var),sizeof(var),1,fp)
 #define read_var(var,fp)  fread((void*)&(var),sizeof(var),1,fp)
+#define write_array_var(var,fp) fwrite((void*)(var),sizeof(var),1,fp)
+#define read_array_var(var,fp)  fread((void*)(var),sizeof(var),1,fp)
 
 static bool
 write_backend_variables(char *filename, Port *port)
@@ -3326,9 +3160,9 @@ write_backend_variables(char *filename, Port *port)
 
 	/* Calculate name for temp file in caller's buffer */
 	Assert(DataDir);
-	snprintf(filename, MAXPGPATH, "%s/%s/%s.backend_var.%lu",
+	snprintf(filename, MAXPGPATH, "%s/%s/%s.backend_var.%d.%lu",
 			 DataDir, PG_TEMP_FILES_DIR, PG_TEMP_FILE_PREFIX,
-			 ++tmpBackendFileNum);
+			 MyProcPid, ++tmpBackendFileNum);
 
 	/* Open file */
 	fp = AllocateFile(filename, PG_BINARY_W);
@@ -3366,7 +3200,9 @@ write_backend_variables(char *filename, Port *port)
 	 */
 
 	StrNCpy(str_buf, DataDir, MAXPGPATH);
-	fwrite((void *) str_buf, MAXPGPATH, 1, fp);
+	write_array_var(str_buf, fp);
+
+	write_array_var(ListenSocket, fp);
 
 	write_var(MyCancelKey, fp);
 
@@ -3386,14 +3222,15 @@ write_backend_variables(char *filename, Port *port)
 	write_var(debug_flag, fp);
 	write_var(PostmasterPid, fp);
 
-	fwrite((void *) my_exec_path, MAXPGPATH, 1, fp);
+	StrNCpy(str_buf, my_exec_path, MAXPGPATH);
+	write_array_var(str_buf, fp);
 
-	fwrite((void *) ExtraOptions, sizeof(ExtraOptions), 1, fp);
+	write_array_var(ExtraOptions, fp);
 
 	StrNCpy(str_buf, setlocale(LC_COLLATE, NULL), MAXPGPATH);
-	fwrite((void *) str_buf, MAXPGPATH, 1, fp);
+	write_array_var(str_buf, fp);
 	StrNCpy(str_buf, setlocale(LC_CTYPE, NULL), MAXPGPATH);
-	fwrite((void *) str_buf, MAXPGPATH, 1, fp);
+	write_array_var(str_buf, fp);
 
 	/* Release file */
 	if (FreeFile(fp))
@@ -3430,9 +3267,11 @@ read_backend_variables(char *filename, Port *port)
 	read_var(port->cryptSalt, fp);
 	read_var(port->md5Salt, fp);
 
-	fread((void *) str_buf, MAXPGPATH, 1, fp);
+	read_array_var(str_buf, fp);
 	SetDataDir(str_buf);
 
+	read_array_var(ListenSocket, fp);
+
 	read_var(MyCancelKey, fp);
 
 	read_var(UsedShmemSegID, fp);
@@ -3451,13 +3290,14 @@ read_backend_variables(char *filename, Port *port)
 	read_var(debug_flag, fp);
 	read_var(PostmasterPid, fp);
 
-	fread((void *) my_exec_path, MAXPGPATH, 1, fp);
+	read_array_var(str_buf, fp);
+	StrNCpy(my_exec_path, str_buf, MAXPGPATH);
 
-	fread((void *) ExtraOptions, sizeof(ExtraOptions), 1, fp);
+	read_array_var(ExtraOptions, fp);
 
-	fread((void *) str_buf, MAXPGPATH, 1, fp);
+	read_array_var(str_buf, fp);
 	setlocale(LC_COLLATE, str_buf);
-	fread((void *) str_buf, MAXPGPATH, 1, fp);
+	read_array_var(str_buf, fp);
 	setlocale(LC_CTYPE, str_buf);
 
 	/* Release file */
@@ -3481,6 +3321,7 @@ ShmemBackendArrayAllocation(void)
 	size_t		size = ShmemBackendArraySize();
 
 	ShmemBackendArray = (Backend *) ShmemAlloc(size);
+	/* Mark all slots as empty */
 	memset(ShmemBackendArray, 0, size);
 }
 
@@ -3489,9 +3330,9 @@ ShmemBackendArrayAdd(Backend *bn)
 {
 	int			i;
 
+	/* Find an empty slot */
 	for (i = 0; i < NUM_BACKENDARRAY_ELEMS; i++)
 	{
-		/* Find an empty slot */
 		if (ShmemBackendArray[i].pid == 0)
 		{
 			ShmemBackendArray[i] = *bn;
@@ -3500,7 +3341,7 @@ ShmemBackendArrayAdd(Backend *bn)
 	}
 
 	ereport(FATAL,
-			(errmsg_internal("unable to add backend entry")));
+			(errmsg_internal("no free slots in shmem backend array")));
 }
 
 static void
@@ -3597,13 +3438,14 @@ win32_forkexec(const char *path, char *argv[])
 }
 
 /*
- * Note: The following three functions must not be interrupted (eg. by signals).
- *	As the Postgres Win32 signalling architecture (currently) requires polling,
- *	or APC checking functions which aren't used here, this is not an issue.
+ * Note: The following three functions must not be interrupted (eg. by
+ * signals).  As the Postgres Win32 signalling architecture (currently)
+ * requires polling, or APC checking functions which aren't used here, this
+ * is not an issue.
  *
- *	We keep two separate arrays, instead of a single array of pid/HANDLE structs,
- *	to avoid having to re-create a handle array for WaitForMultipleObjects on
- *	each call to win32_waitpid.
+ * We keep two separate arrays, instead of a single array of pid/HANDLE
+ * structs, to avoid having to re-create a handle array for
+ * WaitForMultipleObjects on each call to win32_waitpid.
  */
 
 static void
@@ -3662,15 +3504,17 @@ win32_waitpid(int *exitstatus)
 		 */
 		int			index;
 		DWORD		exitCode;
-		DWORD		ret = WaitForMultipleObjects(win32_numChildren, win32_childHNDArray, FALSE, 0);
+		DWORD		ret;
 
+		ret = WaitForMultipleObjects(win32_numChildren, win32_childHNDArray,
+									 FALSE, 0);
 		switch (ret)
 		{
 			case WAIT_FAILED:
-				ereport(ERROR,
-				   (errmsg_internal("failed to wait on %lu children: %i",
+				ereport(LOG,
+				   (errmsg_internal("failed to wait on %lu children: %d",
 							  win32_numChildren, (int) GetLastError())));
-				/* Fall through to WAIT_TIMEOUTs return */
+				return -1;
 
 			case WAIT_TIMEOUT:
 				/* No children have finished */
@@ -3685,7 +3529,7 @@ win32_waitpid(int *exitstatus)
 				index = ret - WAIT_OBJECT_0;
 				Assert(index >= 0 && index < win32_numChildren);
 				if (!GetExitCodeProcess(win32_childHNDArray[index], &exitCode))
-
+				{
 					/*
 					 * If we get this far, this should never happen, but,
 					 * then again... No choice other than to assume a
@@ -3694,6 +3538,7 @@ win32_waitpid(int *exitstatus)
 					ereport(FATAL,
 							(errmsg_internal("failed to get exit code for child %lu",
 										   win32_childPIDArray[index])));
+				}
 				*exitstatus = (int) exitCode;
 				return win32_childPIDArray[index];
 		}
@@ -3703,8 +3548,10 @@ win32_waitpid(int *exitstatus)
 	return -1;
 }
 
-/* Note! Code belows executes on separate threads, one for
-   each child process created */
+/*
+ * Note! Code below executes on separate threads, one for
+ * each child process created
+ */
 static DWORD WINAPI
 win32_sigchld_waiter(LPVOID param)
 {
diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c
index 4f6772564a8df76148624befcdb5997c7a723138..f718e33cd598beddb09c76f8467e18f16017c162 100644
--- a/src/backend/storage/buffer/bufmgr.c
+++ b/src/backend/storage/buffer/bufmgr.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/storage/buffer/bufmgr.c,v 1.165 2004/05/08 19:09:25 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/storage/buffer/bufmgr.c,v 1.166 2004/05/29 22:48:19 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -60,10 +60,6 @@ bool		zero_damaged_pages = false;
 bool			ShowPinTrace = false;
 #endif
 
-int			BgWriterDelay = 200;
-int			BgWriterPercent = 1;
-int			BgWriterMaxpages = 100;
-
 long		NDirectFileRead;	/* some I/O's are direct file access.
 								 * bypass bufmgr */
 long		NDirectFileWrite;	/* e.g., I/O in psort and hashjoin. */
@@ -862,72 +858,6 @@ FlushBufferPool(void)
 }
 
 
-/*
- * BufferBackgroundWriter
- *
- * Periodically flushes dirty blocks from the buffer pool to keep
- * the LRU list clean, preventing regular backends from writing.
- */
-void
-BufferBackgroundWriter(void)
-{
-	if (BgWriterPercent == 0)
-		return;
-
-	/*
-	 * Loop forever 
-	 */
-	for (;;)
-	{
-		int			n;
-		long		udelay;
-
-		/*
-		 * Call BufferSync() with instructions to keep just the
-		 * LRU heads clean.
-		 */
-		n = BufferSync(BgWriterPercent, BgWriterMaxpages);
-
-		/*
-		 * Whatever signal is sent to us, let's just die gallantly. If
-		 * it wasn't meant that way, the postmaster will reincarnate us.
-		 */
-		if (InterruptPending)
-			return;
-
-		/*
-		 * Whenever we have nothing to do, close all smgr files.  This
-		 * is so we won't hang onto smgr references to deleted files
-		 * indefinitely.  XXX this is a bogus, temporary solution.  'Twould
-		 * be much better to do this once per checkpoint, but the bgwriter
-		 * doesn't yet know anything about checkpoints.
-		 */
-		if (n == 0)
-			smgrcloseall();
-
-		/*
-		 * Nap for the configured time or sleep for 10 seconds if
-		 * there was nothing to do at all.
-		 *
-		 * On some platforms, signals won't interrupt the sleep.  To ensure
-		 * we respond reasonably promptly when the postmaster signals us,
-		 * break down the sleep into 1-second increments, and check for
-		 * interrupts after each nap.
-		 */
-		udelay = ((n > 0) ? BgWriterDelay : 10000) * 1000L;
-		while (udelay > 1000000L)
-		{
-			pg_usleep(1000000L);
-			udelay -= 1000000L;
-			if (InterruptPending)
-				return;
-		}
-		pg_usleep(udelay);
-		if (InterruptPending)
-			return;
-	}
-}
-
 /*
  * Do whatever is needed to prepare for commit at the bufmgr and smgr levels
  */
diff --git a/src/backend/storage/ipc/ipci.c b/src/backend/storage/ipc/ipci.c
index 4ce5c98b577bf9cb21b14f2aea186388eb7c6aeb..69c460306b4199d51647abd2d3f409b95f2efd24 100644
--- a/src/backend/storage/ipc/ipci.c
+++ b/src/backend/storage/ipc/ipci.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/storage/ipc/ipci.c,v 1.67 2004/05/28 05:13:03 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/storage/ipc/ipci.c,v 1.68 2004/05/29 22:48:20 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -18,6 +18,7 @@
 #include "miscadmin.h"
 #include "access/clog.h"
 #include "access/xlog.h"
+#include "postmaster/bgwriter.h"
 #include "storage/bufmgr.h"
 #include "storage/freespace.h"
 #include "storage/ipc.h"
@@ -72,6 +73,7 @@ CreateSharedMemoryAndSemaphores(bool makePrivate,
 		size += LWLockShmemSize();
 		size += SInvalShmemSize(maxBackends);
 		size += FreeSpaceShmemSize();
+		size += BgWriterShmemSize();
 #ifdef EXEC_BACKEND
 		size += ShmemBackendArraySize();
 #endif
@@ -155,9 +157,10 @@ CreateSharedMemoryAndSemaphores(bool makePrivate,
 	InitFreeSpaceMap();
 
 	/*
-	 * Set up child-to-postmaster signaling mechanism
+	 * Set up interprocess signaling mechanisms
 	 */
 	PMSignalInit();
+	BgWriterShmemInit();
 
 #ifdef EXEC_BACKEND
 	/*
diff --git a/src/backend/storage/ipc/pmsignal.c b/src/backend/storage/ipc/pmsignal.c
index b0fc1aea0ff2a847592bf3c5601ff7f1e7ff5dcf..4efa4adac6f80ec6d474eac77e924208f1028a75 100644
--- a/src/backend/storage/ipc/pmsignal.c
+++ b/src/backend/storage/ipc/pmsignal.c
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/storage/ipc/pmsignal.c,v 1.13 2004/02/08 22:28:56 neilc Exp $
+ *	  $PostgreSQL: pgsql/src/backend/storage/ipc/pmsignal.c,v 1.14 2004/05/29 22:48:20 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -83,3 +83,41 @@ CheckPostmasterSignal(PMSignalReason reason)
 	}
 	return false;
 }
+
+/*
+ * PostmasterIsAlive - check whether postmaster process is still alive
+ *
+ * amDirectChild should be passed as "true" by code that knows it is
+ * executing in a direct child process of the postmaster; pass "false"
+ * if an indirect child or not sure.  The "true" case uses a faster and
+ * more reliable test, so use it when possible.
+ */
+bool
+PostmasterIsAlive(bool amDirectChild)
+{
+#ifndef WIN32
+	if (amDirectChild)
+	{
+		/*
+		 * If the postmaster is alive, we'll still be its child.  If it's
+		 * died, we'll be reassigned as a child of the init process.
+		 */
+		return (getppid() == PostmasterPid);
+	}
+	else
+	{
+		/*
+		 * Use kill() to see if the postmaster is still alive.  This can
+		 * sometimes give a false positive result, since the postmaster's PID
+		 * may get recycled, but it is good enough for existing uses by
+		 * indirect children.
+		 */
+		return (kill(PostmasterPid, 0) == 0);
+	}
+#else /* WIN32 */
+	/*
+	 * XXX needs to be implemented by somebody
+	 */
+	return true;
+#endif /* WIN32 */
+}
diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c
index 19ce44ff687f46e47adeece77b60763c7fa4db45..dbf5b414153f01238234c0bbfba1e6e7947c01b2 100644
--- a/src/backend/storage/lmgr/proc.c
+++ b/src/backend/storage/lmgr/proc.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/storage/lmgr/proc.c,v 1.147 2004/02/18 16:25:12 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/storage/lmgr/proc.c,v 1.148 2004/05/29 22:48:20 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -68,10 +68,9 @@ PGPROC	   *MyProc = NULL;
  */
 NON_EXEC_STATIC slock_t *ProcStructLock = NULL;
 
+/* Pointers to shared-memory structures */
 static PROC_HDR *ProcGlobal = NULL;
-
-static PGPROC *DummyProc = NULL;
-static int	dummy_proc_type = -1;
+static PGPROC *DummyProcs = NULL;
 
 static bool waitingForLock = false;
 static bool waitingForSignal = false;
@@ -130,17 +129,16 @@ InitProcGlobal(int maxBackends)
 
 	/*
 	 * Create or attach to the PGPROC structures for dummy (checkpoint)
-	 * processes, too.	This does not get linked into the freeProcs
-	 * list.
+	 * processes, too.	These do not get linked into the freeProcs list.
 	 */
-	DummyProc = (PGPROC *)
-		ShmemInitStruct("DummyProc",sizeof(PGPROC) * NUM_DUMMY_PROCS, &foundDummy);
+	DummyProcs = (PGPROC *)
+		ShmemInitStruct("DummyProcs", sizeof(PGPROC) * NUM_DUMMY_PROCS,
+						&foundDummy);
 
 	if (foundProcGlobal || foundDummy)
 	{
 		/* both should be present or neither */
 		Assert(foundProcGlobal && foundDummy);
-		return;
 	}
 	else
 	{
@@ -170,11 +168,11 @@ InitProcGlobal(int maxBackends)
 			ProcGlobal->freeProcs = MAKE_OFFSET(proc);
 		}
 
-		MemSet(DummyProc, 0, sizeof(PGPROC) * NUM_DUMMY_PROCS);
+		MemSet(DummyProcs, 0, sizeof(PGPROC) * NUM_DUMMY_PROCS);
 		for (i = 0; i < NUM_DUMMY_PROCS; i++)
 		{
-			DummyProc[i].pid = 0;		/* marks DummyProc as not in use */
-			PGSemaphoreCreate(&(DummyProc[i].sem));
+			DummyProcs[i].pid = 0;		/* marks dummy proc as not in use */
+			PGSemaphoreCreate(&(DummyProcs[i].sem));
 		}
 
 		/* Create ProcStructLock spinlock, too */
@@ -249,7 +247,6 @@ InitProcess(void)
 	MyProc->waitHolder = NULL;
 	SHMQueueInit(&(MyProc->procHolders));
 
-
 	/*
 	 * Arrange to clean up at backend exit.
 	 */
@@ -274,6 +271,9 @@ InitProcess(void)
  * This is called by checkpoint processes so that they will have a MyProc
  * value that's real enough to let them wait for LWLocks.  The PGPROC and
  * sema that are assigned are the extra ones created during InitProcGlobal.
+ *
+ * Dummy processes are presently not expected to wait for real (lockmgr)
+ * locks, nor to participate in sinval messaging.
  */
 void
 InitDummyProcess(int proctype)
@@ -284,29 +284,29 @@ InitDummyProcess(int proctype)
 	 * ProcGlobal should be set by a previous call to InitProcGlobal (we
 	 * inherit this by fork() from the postmaster).
 	 */
-	if (ProcGlobal == NULL || DummyProc == NULL)
+	if (ProcGlobal == NULL || DummyProcs == NULL)
 		elog(PANIC, "proc header uninitialized");
 
 	if (MyProc != NULL)
 		elog(ERROR, "you already exist");
 
-	Assert(dummy_proc_type < 0);
-	dummy_proc_type = proctype;
-	dummyproc = &DummyProc[proctype];
+	Assert(proctype >= 0 && proctype < NUM_DUMMY_PROCS);
+
+	dummyproc = &DummyProcs[proctype];
 
 	/*
 	 * dummyproc should not presently be in use by anyone else
 	 */
 	if (dummyproc->pid != 0)
 		elog(FATAL, "DummyProc[%d] is in use by PID %d",
-				proctype, dummyproc->pid);
+			 proctype, dummyproc->pid);
 	MyProc = dummyproc;
 
 	/*
 	 * Initialize all fields of MyProc, except MyProc->sem which was set
 	 * up by InitProcGlobal.
 	 */
-	MyProc->pid = MyProcPid;	/* marks DummyProc as in use by me */
+	MyProc->pid = MyProcPid;	/* marks dummy proc as in use by me */
 	SHMQueueElemInit(&(MyProc->links));
 	MyProc->errType = STATUS_OK;
 	MyProc->xid = InvalidTransactionId;
@@ -323,7 +323,7 @@ InitDummyProcess(int proctype)
 	/*
 	 * Arrange to clean up at process exit.
 	 */
-	on_shmem_exit(DummyProcKill, proctype);
+	on_shmem_exit(DummyProcKill, Int32GetDatum(proctype));
 
 	/*
 	 * We might be reusing a semaphore that belonged to a failed process.
@@ -459,13 +459,14 @@ ProcKill(int code, Datum arg)
 static void
 DummyProcKill(int code, Datum arg)
 {
+	int		proctype = DatumGetInt32(arg);
 	PGPROC	*dummyproc;
 
-	Assert(dummy_proc_type >= 0 && dummy_proc_type < NUM_DUMMY_PROCS);
+	Assert(proctype >= 0 && proctype < NUM_DUMMY_PROCS);
 
-	dummyproc = &DummyProc[dummy_proc_type];
+	dummyproc = &DummyProcs[proctype];
 
-	Assert(MyProc != NULL && MyProc == dummyproc);
+	Assert(MyProc == dummyproc);
 
 	/* Release any LW locks I am holding */
 	LWLockReleaseAll();
@@ -477,13 +478,11 @@ DummyProcKill(int code, Datum arg)
 
 	/* I can't be on regular lock queues, so needn't check */
 
-	/* Mark DummyProc no longer in use */
+	/* Mark dummy proc no longer in use */
 	MyProc->pid = 0;
 
 	/* PGPROC struct isn't mine anymore */
 	MyProc = NULL;
-
-	dummy_proc_type = -1;
 }
 
 
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 7acaf9117db22ff8921d29bd7872d46d93a55b45..556528d6d2d1fda6e2ba77bf01eb18f6c77c64e6 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.416 2004/05/28 05:13:12 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.417 2004/05/29 22:48:20 tgl Exp $
  *
  * NOTES
  *	  this is the "main" module of the postgres backend and
@@ -110,7 +110,7 @@ static char *stack_base_ptr = NULL;
  * will reread the configuration file. (Better than doing the
  * reading in the signal handler, ey?)
  */
-static volatile bool got_SIGHUP = false;
+static volatile sig_atomic_t got_SIGHUP = false;
 
 /*
  * Flag to keep track of whether we have started a transaction.
diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c
index 39b69c6248c2e6fb34eacaf49c9e8da99a22d37d..4d6c246cea1a8ba483f14670889e1abc881d834b 100644
--- a/src/backend/tcop/utility.c
+++ b/src/backend/tcop/utility.c
@@ -10,7 +10,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/tcop/utility.c,v 1.217 2004/05/26 13:56:54 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/tcop/utility.c,v 1.218 2004/05/29 22:48:20 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -45,6 +45,7 @@
 #include "nodes/makefuncs.h"
 #include "parser/parse_expr.h"
 #include "parser/parse_type.h"
+#include "postmaster/bgwriter.h"
 #include "rewrite/rewriteDefine.h"
 #include "rewrite/rewriteRemove.h"
 #include "storage/fd.h"
@@ -54,7 +55,7 @@
 #include "utils/guc.h"
 #include "utils/lsyscache.h"
 #include "utils/syscache.h"
-#include "access/xlog.h"
+
 
 /*
  * Error-checking support for DROP commands
@@ -892,7 +893,7 @@ ProcessUtility(Node *parsetree,
 				ereport(ERROR,
 						(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
 						 errmsg("must be superuser to do CHECKPOINT")));
-			CreateCheckPoint(false, false);
+			RequestCheckpoint(true);
 			break;
 
 		case T_ReindexStmt:
diff --git a/src/backend/utils/error/elog.c b/src/backend/utils/error/elog.c
index b76c4cb88b0941df0d3f66c7248c32e8464db0e4..e3adab82979d3f50aac2c5406d9702eda8b2a407 100644
--- a/src/backend/utils/error/elog.c
+++ b/src/backend/utils/error/elog.c
@@ -37,7 +37,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/utils/error/elog.c,v 1.138 2004/05/28 03:11:15 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/utils/error/elog.c,v 1.139 2004/05/29 22:48:21 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -57,6 +57,7 @@
 #include "mb/pg_wchar.h"
 #include "miscadmin.h"
 #include "pgtime.h"
+#include "postmaster/postmaster.h"
 #include "storage/ipc.h"
 #include "tcop/tcopprot.h"
 #include "utils/memutils.h"
diff --git a/src/backend/utils/init/globals.c b/src/backend/utils/init/globals.c
index 85c3e23a019a9e2f1638f5454d97d891f3879ab5..2a22f666f6d29953e23e07d747c978e1a074024c 100644
--- a/src/backend/utils/init/globals.c
+++ b/src/backend/utils/init/globals.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/utils/init/globals.c,v 1.88 2004/05/28 05:13:15 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/utils/init/globals.c,v 1.89 2004/05/29 22:48:21 tgl Exp $
  *
  * NOTES
  *	  Globals used all over the place should be declared here and not
@@ -85,7 +85,10 @@ bool		enableFsync = true;
 bool		allowSystemTableMods = false;
 int			work_mem = 1024;
 int			maintenance_work_mem = 16384;
+
+/* Primary determinants of sizes of shared-memory structures: */
 int			NBuffers = 1000;
+int			MaxBackends = 100;
 
 int			VacuumCostPageHit = 1;			/* GUC parameters for vacuum */
 int			VacuumCostPageMiss = 10;
diff --git a/src/backend/utils/init/postinit.c b/src/backend/utils/init/postinit.c
index 69d4d974099d0b8794af15f3c6f63ab7038be85c..e80187d57523403ad6ae1bd424f173f58e14d15a 100644
--- a/src/backend/utils/init/postinit.c
+++ b/src/backend/utils/init/postinit.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/utils/init/postinit.c,v 1.132 2004/05/27 17:12:54 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/utils/init/postinit.c,v 1.133 2004/05/29 22:48:21 tgl Exp $
  *
  *
  *-------------------------------------------------------------------------
@@ -29,6 +29,7 @@
 #include "commands/trigger.h"
 #include "mb/pg_wchar.h"
 #include "miscadmin.h"
+#include "postmaster/postmaster.h"
 #include "storage/backendid.h"
 #include "storage/ipc.h"
 #include "storage/proc.h"
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 1620a8607c28c8e351ece360c3a8de19064b9bed..eda37c1be2c46c39010b4ed03cc0bc4cac8bac60 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -10,7 +10,7 @@
  * Written by Peter Eisentraut <peter_e@gmx.net>.
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.208 2004/05/26 15:07:39 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.209 2004/05/29 22:48:21 tgl Exp $
  *
  *--------------------------------------------------------------------
  */
@@ -44,6 +44,8 @@
 #include "optimizer/prep.h"
 #include "parser/parse_expr.h"
 #include "parser/parse_relation.h"
+#include "postmaster/bgwriter.h"
+#include "postmaster/postmaster.h"
 #include "storage/bufmgr.h"
 #include "storage/fd.h"
 #include "storage/freespace.h"
@@ -65,15 +67,10 @@
 #endif
 
 /* XXX these should appear in other modules' header files */
-extern bool Log_connections;
 extern bool Log_disconnections;
 extern DLLIMPORT bool check_function_bodies;
-extern int	PreAuthDelay;
-extern int	AuthenticationTimeout;
-extern int	CheckPointTimeout;
 extern int	CommitDelay;
 extern int	CommitSiblings;
-extern char *preload_libraries_string;
 extern int	DebugSharedBuffers;
 
 static const char *assign_log_destination(const char *value,
@@ -1262,7 +1259,7 @@ static struct config_int ConfigureNamesInt[] =
 			NULL
 		},
 		&BgWriterPercent,
-		1, 0, 100, NULL, NULL
+		1, 1, 100, NULL, NULL
 	},
 
 	{
@@ -1270,7 +1267,7 @@ static struct config_int ConfigureNamesInt[] =
 			gettext_noop("Background writer maximum number of pages to flush per round"),
 			NULL
 		},
-		&BgWriterMaxpages,
+		&BgWriterMaxPages,
 		100, 1, 1000, NULL, NULL
 	},
 
diff --git a/src/include/access/xlog.h b/src/include/access/xlog.h
index b0ebedcf329939b91825d399b1a3ab2ddbb576be..0e44e77446d650f98243117fbf26041903c1a378 100644
--- a/src/include/access/xlog.h
+++ b/src/include/access/xlog.h
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/access/xlog.h,v 1.50 2004/05/27 17:12:57 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/access/xlog.h,v 1.51 2004/05/29 22:48:22 tgl Exp $
  */
 #ifndef XLOG_H
 #define XLOG_H
@@ -207,7 +207,6 @@ extern XLogRecPtr ProcLastRecEnd;
 
 /* these variables are GUC parameters related to XLOG */
 extern int	CheckPointSegments;
-extern int	CheckPointWarning;
 extern int	XLOGbuffers;
 extern char *XLOG_sync_method;
 extern const char XLOG_sync_method_default[];
diff --git a/src/include/bootstrap/bootstrap.h b/src/include/bootstrap/bootstrap.h
index 7dd9c808fded8c933bf587b2f3dd32fe950f2c4e..21ed48286927ff3470fd93e72000f8ef955f249b 100644
--- a/src/include/bootstrap/bootstrap.h
+++ b/src/include/bootstrap/bootstrap.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/bootstrap/bootstrap.h,v 1.34 2004/05/28 05:13:21 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/bootstrap/bootstrap.h,v 1.35 2004/05/29 22:48:22 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -58,8 +58,6 @@ extern void Int_yyerror(const char *str);
 #define BS_XLOG_NOP			0
 #define BS_XLOG_BOOTSTRAP	1
 #define BS_XLOG_STARTUP		2
-#define BS_XLOG_CHECKPOINT	3
-#define BS_XLOG_BGWRITER	4
-#define BS_XLOG_SHUTDOWN	5
+#define BS_XLOG_BGWRITER	3
 
 #endif   /* BOOTSTRAP_H */
diff --git a/src/include/miscadmin.h b/src/include/miscadmin.h
index e8e35fd6b58c24db5e060724eac34b8958fd9a9e..4561d2fcfb76a9f15ac145659e091f8e3218cbe2 100644
--- a/src/include/miscadmin.h
+++ b/src/include/miscadmin.h
@@ -13,11 +13,10 @@
  * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/miscadmin.h,v 1.161 2004/05/28 05:13:24 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/miscadmin.h,v 1.162 2004/05/29 22:48:22 tgl Exp $
  *
  * NOTES
- *	  some of the information in this file should be moved to
- *	  other files.
+ *	  some of the information in this file should be moved to other files.
  *
  *-------------------------------------------------------------------------
  */
@@ -25,6 +24,9 @@
 #define MISCADMIN_H
 
 
+#define PG_VERSIONSTR "postgres (PostgreSQL) " PG_VERSION "\n"
+
+
 /*****************************************************************************
  *	  System interrupt and critical section handling
  *
@@ -75,12 +77,15 @@ extern volatile uint32 CritSectionCount;
 extern void ProcessInterrupts(void);
 
 #ifndef WIN32
+
 #define CHECK_FOR_INTERRUPTS() \
 do { \
 	if (InterruptPending) \
 		ProcessInterrupts(); \
 } while(0)
-#else
+
+#else  /* WIN32 */
+
 #define CHECK_FOR_INTERRUPTS() \
 do { \
 	if (WaitForSingleObject(pgwin32_signal_event,0) == WAIT_OBJECT_0) \
@@ -88,7 +93,8 @@ do { \
 	if (InterruptPending) \
 		ProcessInterrupts(); \
 } while(0)
-#endif
+
+#endif /* WIN32 */
 
 
 #define HOLD_INTERRUPTS()  (InterruptHoldoffCount++)
@@ -112,20 +118,6 @@ do { \
  *	  globals.h --															 *
  *****************************************************************************/
 
-/*
- * from postmaster/postmaster.c
- */
-extern bool ClientAuthInProgress;
-
-extern int	PostmasterMain(int argc, char *argv[]);
-extern void ClosePostmasterPorts(bool pgstat_too);
-#ifdef EXEC_BACKEND
-extern pid_t postmaster_forkexec(int argc, char *argv[]);
-extern int	SubPostmasterMain(int argc, char *argv[]);
-#endif
-
-#define PG_VERSIONSTR "postgres (PostgreSQL) " PG_VERSION "\n"
-
 /*
  * from utils/init/globals.c
  */
@@ -137,6 +129,9 @@ extern bool ExitOnAnyError;
 
 extern char *DataDir;
 
+extern DLLIMPORT int NBuffers;
+extern int	MaxBackends;
+
 extern DLLIMPORT int MyProcPid;
 extern struct Port *MyProcPort;
 extern long MyCancelKey;
@@ -216,21 +211,6 @@ extern int	VacuumCostNaptime;
 extern int	VacuumCostBalance;
 extern bool	VacuumCostActive;
 
-/*
- *	A few postmaster startup options are exported here so the
- *	configuration file processor can access them.
- */
-extern bool EnableSSL;
-extern bool SilentMode;
-extern int	MaxBackends;
-extern int	ReservedBackends;
-extern DLLIMPORT int NBuffers;
-extern int	PostPortNumber;
-extern int	Unix_socket_permissions;
-extern char *Unix_socket_group;
-extern char *UnixSocketDir;
-extern char *ListenAddresses;
-
 
 /* in tcop/postgres.c */
 extern void check_stack_depth(void);
diff --git a/src/include/pgstat.h b/src/include/pgstat.h
index 8f7c4dc4515b7aaa1905f749d274b761f74de5d4..96d3af7ab051978f6ab4c957e3a1b8d049402e02 100644
--- a/src/include/pgstat.h
+++ b/src/include/pgstat.h
@@ -5,7 +5,7 @@
  *
  *	Copyright (c) 2001-2003, PostgreSQL Global Development Group
  *
- *	$PostgreSQL: pgsql/src/include/pgstat.h,v 1.22 2004/05/28 05:13:25 tgl Exp $
+ *	$PostgreSQL: pgsql/src/include/pgstat.h,v 1.23 2004/05/29 22:48:22 tgl Exp $
  * ----------
  */
 #ifndef PGSTAT_H
@@ -349,7 +349,6 @@ extern bool pgstat_is_running;
 extern void pgstat_init(void);
 extern void pgstat_start(void);
 extern bool pgstat_ispgstat(int pid);
-extern void pgstat_close_sockets(void);
 extern void pgstat_beterm(int pid);
 
 #ifdef EXEC_BACKEND
diff --git a/src/include/postmaster/bgwriter.h b/src/include/postmaster/bgwriter.h
new file mode 100644
index 0000000000000000000000000000000000000000..c11af72e78945f91dfe76bfab00eeab7eabea886
--- /dev/null
+++ b/src/include/postmaster/bgwriter.h
@@ -0,0 +1,29 @@
+/*-------------------------------------------------------------------------
+ *
+ * bgwriter.h
+ *	  Exports from postmaster/bgwriter.c.
+ *
+ * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
+ *
+ * $PostgreSQL: pgsql/src/include/postmaster/bgwriter.h,v 1.1 2004/05/29 22:48:23 tgl Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef _BGWRITER_H
+#define _BGWRITER_H
+
+/* GUC options */
+extern int	BgWriterDelay;
+extern int	BgWriterPercent;
+extern int	BgWriterMaxPages;
+extern int	CheckPointTimeout;
+extern int	CheckPointWarning;
+
+extern void BackgroundWriterMain(void);
+
+extern void RequestCheckpoint(bool waitforit);
+
+extern int	BgWriterShmemSize(void);
+extern void BgWriterShmemInit(void);
+
+#endif   /* _BGWRITER_H */
diff --git a/src/include/postmaster/postmaster.h b/src/include/postmaster/postmaster.h
new file mode 100644
index 0000000000000000000000000000000000000000..d349018f4b5ecf0e56a3843c93756328cb0a3bcb
--- /dev/null
+++ b/src/include/postmaster/postmaster.h
@@ -0,0 +1,41 @@
+/*-------------------------------------------------------------------------
+ *
+ * postmaster.h
+ *	  Exports from postmaster/postmaster.c.
+ *
+ * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * $PostgreSQL: pgsql/src/include/postmaster/postmaster.h,v 1.1 2004/05/29 22:48:23 tgl Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef _POSTMASTER_H
+#define _POSTMASTER_H
+
+/* GUC options */
+extern bool EnableSSL;
+extern bool SilentMode;
+extern int	ReservedBackends;
+extern int	PostPortNumber;
+extern int	Unix_socket_permissions;
+extern char *Unix_socket_group;
+extern char *UnixSocketDir;
+extern char *ListenAddresses;
+extern bool ClientAuthInProgress;
+extern int	PreAuthDelay;
+extern int	AuthenticationTimeout;
+extern char *preload_libraries_string;
+extern bool Log_connections;
+extern bool log_hostname;
+extern char *rendezvous_name;
+
+
+extern int	PostmasterMain(int argc, char *argv[]);
+extern void ClosePostmasterPorts(void);
+#ifdef EXEC_BACKEND
+extern pid_t postmaster_forkexec(int argc, char *argv[]);
+extern int	SubPostmasterMain(int argc, char *argv[]);
+#endif
+
+#endif   /* _POSTMASTER_H */
diff --git a/src/include/storage/bufmgr.h b/src/include/storage/bufmgr.h
index 0aab9ad24f4466d39e3a2354cae535d0d031ad73..27752d412b56435ddbe61bf77adcd83554d1df92 100644
--- a/src/include/storage/bufmgr.h
+++ b/src/include/storage/bufmgr.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/storage/bufmgr.h,v 1.79 2004/05/08 19:09:25 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/storage/bufmgr.h,v 1.80 2004/05/29 22:48:23 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -28,11 +28,6 @@ extern DLLIMPORT int NBuffers;
 /* in bufmgr.c */
 extern bool zero_damaged_pages;
 
-extern int	BgWriterDelay;
-extern int	BgWriterPercent;
-extern int	BgWriterMaxpages;
-
-
 /* in buf_init.c */
 extern DLLIMPORT Block *BufferBlockPointers;
 extern int32 *PrivateRefCount;
@@ -179,9 +174,6 @@ extern void AbortBufferIO(void);
 
 extern void BufmgrCommit(void);
 extern int	BufferSync(int percent, int maxpages);
-extern void BufferBackgroundWriter(void);
-extern const char *BgWriterAssignSyncMethod(const char *method,
-			bool doid, bool interactive);
 
 extern void InitLocalBuffer(void);
 
diff --git a/src/include/storage/pmsignal.h b/src/include/storage/pmsignal.h
index 688b83adab17bec45cc2013ecaf07e5695d96fc1..4180c95c735654e97c98d2ddb0c35ca27297349c 100644
--- a/src/include/storage/pmsignal.h
+++ b/src/include/storage/pmsignal.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/storage/pmsignal.h,v 1.7 2004/05/23 03:50:45 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/storage/pmsignal.h,v 1.8 2004/05/29 22:48:23 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -22,7 +22,6 @@
  */
 typedef enum
 {
-	PMSIGNAL_DO_CHECKPOINT,		/* request to start a checkpoint */
 	PMSIGNAL_PASSWORD_CHANGE,	/* pg_pwd file has changed */
 	PMSIGNAL_WAKEN_CHILDREN,	/* send a SIGUSR1 signal to all backends */
 
@@ -35,5 +34,6 @@ typedef enum
 extern void PMSignalInit(void);
 extern void SendPostmasterSignal(PMSignalReason reason);
 extern bool CheckPostmasterSignal(PMSignalReason reason);
+extern bool PostmasterIsAlive(bool amDirectChild);
 
 #endif   /* PMSIGNAL_H */
diff --git a/src/include/tcop/tcopprot.h b/src/include/tcop/tcopprot.h
index 97556ccbf1de1fb1a4df065c643d0c3e810f5c8e..1218e04fdfbc821077aca83d1ec1fd2260d0d91b 100644
--- a/src/include/tcop/tcopprot.h
+++ b/src/include/tcop/tcopprot.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/tcop/tcopprot.h,v 1.65 2004/04/11 00:54:45 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/tcop/tcopprot.h,v 1.66 2004/05/29 22:48:23 tgl Exp $
  *
  * OLD COMMENTS
  *	  This file was created so that other c files could get the two
@@ -30,9 +30,7 @@ extern DLLIMPORT sigjmp_buf Warn_restart;
 extern bool Warn_restart_ready;
 extern bool InError;
 extern CommandDest whereToSendOutput;
-extern bool log_hostname;
 extern DLLIMPORT const char *debug_query_string;
-extern char *rendezvous_name;
 extern int	max_stack_depth;
 extern bool in_fatal_exit;