diff --git a/src/backend/access/transam/xact.c b/src/backend/access/transam/xact.c
index 6cd089fd9594e5f5b48022c3dbf629ca7a66accf..c8c9e680f5ffce1d2915c6fe84a3ca1168f8b4a0 100644
--- a/src/backend/access/transam/xact.c
+++ b/src/backend/access/transam/xact.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/access/transam/xact.c,v 1.88 2000/12/07 10:03:46 inoue Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/access/transam/xact.c,v 1.89 2000/12/18 00:44:45 tgl Exp $
  *
  * NOTES
  *		Transaction aborts can now occur two ways:
@@ -1095,6 +1095,15 @@ AbortTransaction(void)
 		MyProc->xmin = InvalidTransactionId;
 	}
 
+	/*
+	 * Release any spinlocks or buffer context locks we might be holding
+	 * as quickly as possible.  (Real locks, however, must be held till
+	 * we finish aborting.)  Releasing spinlocks is critical since we
+	 * might try to grab them again while cleaning up!
+	 */
+	ProcReleaseSpins(NULL);
+	UnlockBuffers();
+
 	/* ----------------
 	 *	check the current transaction state
 	 * ----------------
@@ -1105,18 +1114,6 @@ AbortTransaction(void)
 	if (s->state != TRANS_INPROGRESS)
 		elog(NOTICE, "AbortTransaction and not in in-progress state");
 
-	/*
-	 * Reset user id which might have been changed transiently
-	 */
-	SetUserId(GetSessionUserId());
-
-	/* ----------------
-	 *	Tell the trigger manager that this transaction is about to be
-	 *	aborted.
-	 * ----------------
-	 */
-	DeferredTriggerAbortXact();
-
 	/* ----------------
 	 *	set the current transaction state information
 	 *	appropriately during the abort processing
@@ -1124,12 +1121,17 @@ AbortTransaction(void)
 	 */
 	s->state = TRANS_ABORT;
 
+	/*
+	 * Reset user id which might have been changed transiently
+	 */
+	SetUserId(GetSessionUserId());
+
 	/* ----------------
 	 *	do abort processing
 	 * ----------------
 	 */
+	DeferredTriggerAbortXact();
 	lo_commit(false);			/* 'false' means it's abort */
-	UnlockBuffers();
 	AtAbort_Notify();
 	CloseSequences();
 	AtEOXact_portals();
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 3b2c5461dcd8376f5007d8ef0d72d6167650bc81..ba85f4b60d0ea3f117b3c5d0233b9d0b38fd60c7 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Header: /cvsroot/pgsql/src/backend/access/transam/xlog.c,v 1.42 2000/12/11 19:27:42 vadim Exp $
+ * $Header: /cvsroot/pgsql/src/backend/access/transam/xlog.c,v 1.43 2000/12/18 00:44:45 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -40,7 +40,7 @@
 
 int			XLOGbuffers = 8;
 XLogRecPtr	MyLastRecPtr = {0, 0};
-uint32		StopIfError = 0;
+uint32		CritSectionCount = 0;
 bool		InRecovery = false;
 StartUpID	ThisStartUpID = 0;
 
@@ -1531,7 +1531,7 @@ StartupXLOG()
 	char		buffer[MAXLOGRECSZ + SizeOfXLogRecord];
 
 	elog(LOG, "starting up");
-	StopIfError++;
+	CritSectionCount++;
 
 	XLogCtl->xlblocks = (XLogRecPtr *) (((char *) XLogCtl) + sizeof(XLogCtlData));
 	XLogCtl->pages = ((char *) XLogCtl->xlblocks + sizeof(XLogRecPtr) * XLOGbuffers);
@@ -1748,7 +1748,7 @@ StartupXLOG()
 	XLogCtl->ThisStartUpID = ThisStartUpID;
 
 	elog(LOG, "database system is in production state");
-	StopIfError--;
+	CritSectionCount--;
 
 	return;
 }
@@ -1771,10 +1771,10 @@ ShutdownXLOG()
 {
 	elog(LOG, "shutting down");
 
-	StopIfError++;
+	CritSectionCount++;
 	CreateDummyCaches();
 	CreateCheckPoint(true);
-	StopIfError--;
+	CritSectionCount--;
 
 	elog(LOG, "database system is shut down");
 }
diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c
index cc31a0eb48bce75b705bb89662ca200f30cb8498..d5946ebd3eba9769e0f39484981c01508d371804 100644
--- a/src/backend/commands/trigger.c
+++ b/src/backend/commands/trigger.c
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/commands/trigger.c,v 1.81 2000/11/20 20:36:47 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/trigger.c,v 1.82 2000/12/18 00:44:46 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1432,7 +1432,7 @@ deferredTriggerInvokeEvents(bool immediate_only)
  *	transactions.
  * ----------
  */
-int
+void
 DeferredTriggerInit(void)
 {
 	deftrig_gcxt = AllocSetContextCreate(TopMemoryContext,
@@ -1440,8 +1440,6 @@ DeferredTriggerInit(void)
 										 ALLOCSET_DEFAULT_MINSIZE,
 										 ALLOCSET_DEFAULT_INITSIZE,
 										 ALLOCSET_DEFAULT_MAXSIZE);
-
-	return 0;
 }
 
 
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 35d6802a5a5184af0fcb55c5b3dd1900e5374c7e..0d2548c96af59d1055369c616c0655ffec676f64 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -29,7 +29,7 @@
  * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- *	$Id: pqcomm.c,v 1.114 2000/11/29 20:59:51 tgl Exp $
+ *	$Id: pqcomm.c,v 1.115 2000/12/18 00:44:46 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -85,6 +85,9 @@
 #endif
 
 
+static void pq_close(void);
+
+
 /*
  * Configuration options
  */
@@ -122,6 +125,7 @@ pq_init(void)
 {
 	PqSendPointer = PqRecvPointer = PqRecvLength = 0;
 	DoingCopyOut = false;
+	on_proc_exit(pq_close, 0);
 }
 
 
@@ -132,7 +136,7 @@ pq_init(void)
  * don't crash during exit...
  * --------------------------------
  */
-void
+static void
 pq_close(void)
 {
 	if (MyProcPort != NULL)
diff --git a/src/backend/storage/buffer/buf_init.c b/src/backend/storage/buffer/buf_init.c
index 19b71933d762766c9864d9c2cc9a75379ca08479..54b9d02e1600e50563db093623ae1ca2fa32286b 100644
--- a/src/backend/storage/buffer/buf_init.c
+++ b/src/backend/storage/buffer/buf_init.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/storage/buffer/buf_init.c,v 1.39 2000/11/30 01:39:07 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/storage/buffer/buf_init.c,v 1.40 2000/12/18 00:44:46 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -36,6 +36,9 @@
 #include "utils/hsearch.h"
 #include "utils/memutils.h"
 
+
+static void ShutdownBufferPoolAccess(void);
+
 /*
  *	if BMTRACE is defined, we trace the last 200 buffer allocations and
  *	deallocations in a circular buffer in shared memory.
@@ -73,7 +76,7 @@ bool		   *BufferDirtiedByMe;	/* T if buf has been dirtied in cur xact */
  *		Two important notes.  First, the buffer has to be
  *		available for lookup BEFORE an IO begins.  Otherwise
  *		a second process trying to read the buffer will
- *		allocate its own copy and the buffeer pool will
+ *		allocate its own copy and the buffer pool will
  *		become inconsistent.
  *
  * Buffer Replacement:
@@ -126,10 +129,10 @@ long int	LocalBufferFlushCount;
 
 
 /*
- * Initialize module: called once during shared-memory initialization
+ * Initialize shared buffer pool
  *
- * should calculate size of pool dynamically based on the
- * amount of available memory.
+ * This is called once during shared-memory initialization (either in the
+ * postmaster, or in a standalone backend).
  */
 void
 InitBufferPool(void)
@@ -144,6 +147,10 @@ InitBufferPool(void)
 	Lookup_List_Descriptor = Data_Descriptors + 1;
 	Num_Descriptors = Data_Descriptors + 1;
 
+	/*
+	 * It's probably not really necessary to grab the lock --- if there's
+	 * anyone else attached to the shmem at this point, we've got problems.
+	 */
 	SpinAcquire(BufMgrLock);
 
 #ifdef BMTRACE
@@ -203,12 +210,28 @@ InitBufferPool(void)
 		BufferDescriptors[Data_Descriptors - 1].freeNext = 0;
 	}
 
-	/* Init the rest of the module */
+	/* Init other shared buffer-management stuff */
 	InitBufTable();
 	InitFreeList(!foundDescs);
 
 	SpinRelease(BufMgrLock);
+}
+
+/*
+ * Initialize access to shared buffer pool
+ *
+ * This is called during backend startup (whether standalone or under the
+ * postmaster).  It sets up for this backend's access to the already-existing
+ * buffer pool.
+ */
+void
+InitBufferPoolAccess(void)
+{
+	int			i;
 
+	/*
+	 * Allocate and zero local arrays of per-buffer info.
+	 */
 	BufferBlockPointers = (Block *) calloc(NBuffers, sizeof(Block));
 	PrivateRefCount = (long *) calloc(NBuffers, sizeof(long));
 	BufferLocks = (bits8 *) calloc(NBuffers, sizeof(bits8));
@@ -224,6 +247,27 @@ InitBufferPool(void)
 	{
 		BufferBlockPointers[i] = (Block) MAKE_PTR(BufferDescriptors[i].data);
 	}
+
+	/*
+	 * Now that buffer access is initialized, set up a callback to shut it
+	 * down again at backend exit.
+	 */
+	on_shmem_exit(ShutdownBufferPoolAccess, 0);
+}
+
+/*
+ * Shut down buffer manager at backend exit.
+ *
+ * This is needed mainly to ensure that we don't leave any buffer reference
+ * counts set during an error exit.
+ */
+static void
+ShutdownBufferPoolAccess(void)
+{
+	/* Release any buffer context locks we are holding */
+	UnlockBuffers();
+	/* Release any buffer reference counts we are holding */
+	ResetBufferPool(false);
 }
 
 /* -----------------------------------------------------
diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c
index 29502c30161ffa3a71039f1193b8a632225943b6..a95432e0f8216c1f9ca5c2ffea65705bf0dbcb62 100644
--- a/src/backend/storage/lmgr/proc.c
+++ b/src/backend/storage/lmgr/proc.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/storage/lmgr/proc.c,v 1.86 2000/12/11 16:35:59 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/storage/lmgr/proc.c,v 1.87 2000/12/18 00:44:47 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -29,7 +29,8 @@
  *
  * Interface (b):
  *
- * ProcReleaseLocks -- frees the locks associated with this process,
+ * ProcReleaseLocks -- frees the locks associated with current transaction
+ *
  * ProcKill -- destroys the shared memory state (and locks)
  *		associated with the process.
  *
@@ -47,7 +48,7 @@
  *		This is so that we can support more backends. (system-wide semaphore
  *		sets run out pretty fast.)				  -ay 4/95
  *
- * $Header: /cvsroot/pgsql/src/backend/storage/lmgr/proc.c,v 1.86 2000/12/11 16:35:59 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/storage/lmgr/proc.c,v 1.87 2000/12/18 00:44:47 tgl Exp $
  */
 #include "postgres.h"
 
@@ -332,7 +333,7 @@ GetOffWaitqueue(PROC *proc)
 }
 
 /*
- * ProcReleaseLocks() -- release all locks associated with this process
+ * ProcReleaseLocks() -- release all locks associated with current transaction
  *
  */
 void
@@ -340,7 +341,7 @@ ProcReleaseLocks()
 {
 	if (!MyProc)
 		return;
-	LockReleaseAll(1, &MyProc->lockQueue);
+	LockReleaseAll(DEFAULT_LOCKMETHOD, &MyProc->lockQueue);
 	GetOffWaitqueue(MyProc);
 }
 
@@ -423,8 +424,6 @@ ProcKill(int exitStatus, Datum pid)
 	 * ----------------
 	 */
 	GetOffWaitqueue(proc);
-
-	return;
 }
 
 /*
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 3d74d187ff93575307776c9ae43daff78c2e6f86..706b5d1fbf136606dbcc5d3de7aff436eb26dd6e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.194 2000/12/03 10:27:27 vadim Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.195 2000/12/18 00:44:47 tgl Exp $
  *
  * NOTES
  *	  this is the "main" module of the postgres backend and
@@ -61,7 +61,6 @@
 #include "utils/guc.h"
 #include "utils/memutils.h"
 #include "utils/ps_status.h"
-#include "utils/temprel.h"
 #ifdef MULTIBYTE
 #include "mb/pg_wchar.h"
 #endif
@@ -95,7 +94,7 @@ DLLIMPORT sigjmp_buf Warn_restart;
 
 bool		Warn_restart_ready = false;
 bool		InError = false;
-bool		ExitAfterAbort = false;
+bool		ProcDiePending = false;
 
 static bool EchoQuery = false;	/* default don't echo */
 char		pg_pathname[MAXPGPATH];
@@ -921,7 +920,8 @@ finish_xact_command(void)
 void
 handle_warn(SIGNAL_ARGS)
 {
-	if (StopIfError)
+	/* Don't joggle the elbow of a critical section */
+	if (CritSectionCount > 0)
 	{
 		QueryCancel = true;
 		return;
@@ -958,13 +958,15 @@ die(SIGNAL_ARGS)
 {
 	PG_SETMASK(&BlockSig);
 
-	ExitAfterAbort = true;
-	if (StopIfError)
+	/* Don't joggle the elbow of a critical section */
+	if (CritSectionCount > 0)
 	{
 		QueryCancel = true;
+		ProcDiePending = true;
 		return;
 	}
-	if (InError)	/* If ERROR/FATAL is in progress... */
+	/* Don't joggle the elbow of proc_exit, either */
+	if (proc_exit_inprogress)
 		return;
 	elog(FATAL, "The system is shutting down");
 }
@@ -1096,6 +1098,8 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[], const cha
 		MemoryContextInit();
 	}
 
+	SetProcessingMode(InitProcessing);
+
 	/*
 	 * Set default values for command-line options.
 	 */
@@ -1109,8 +1113,6 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[], const cha
 	}
 	StatFp = stderr;
 
-	SetProcessingMode(InitProcessing);
-
 	/* Check for PGDATESTYLE environment variable */
 	set_default_datestyle();
 
@@ -1428,11 +1430,16 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[], const cha
 				break;
 		}
 
-
+	/*
+	 * Post-processing for command line options.
+	 *
+	 * XXX It'd be nice if libpq were already running here, so we could do
+	 * elog(NOTICE) instead of just writing on stderr...
+	 */
 	if (Show_query_stats &&
 		(Show_parser_stats || Show_planner_stats || Show_executor_stats))
 	{
-		elog(NOTICE, "Query statistics are disabled because parser, planner, or executor statistics are on.");
+		fprintf(stderr, "Query statistics are disabled because parser, planner, or executor statistics are on.\n");
 		Show_query_stats = false;
 	}
 
@@ -1528,7 +1535,13 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[], const cha
 
 		XLOGPathInit();
 		BaseInit();
+
+		/*
+		 * Start up xlog for standalone backend, and register to have it
+		 * closed down at exit.
+		 */
 		StartupXLOG();
+		on_shmem_exit(ShutdownXLOG, 0);
 	}
 
 	/*
@@ -1602,20 +1615,17 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[], const cha
 			 remote_host, username, DBName);
 
 	/*
-	 * general initialization
+	 * General initialization.
+	 *
+	 * NOTE: if you are tempted to add code in this vicinity, consider
+	 * putting it inside InitPostgres() instead.  In particular, anything
+	 * that involves database access should be there, not here.
 	 */
 	if (DebugLvl > 1)
 		elog(DEBUG, "InitPostgres");
 	InitPostgres(DBName, username);
 
-#ifdef MULTIBYTE
-	/* set default client encoding */
-	if (DebugLvl > 1)
-		elog(DEBUG, "set_default_client_encoding");
-	set_default_client_encoding();
-#endif
-
-	on_shmem_exit(remove_all_temp_relations, 0);
+	SetProcessingMode(NormalProcessing);
 
 	/*
 	 * Send this backend's cancellation info to the frontend.
@@ -1636,17 +1646,9 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[], const cha
 	if (!IsUnderPostmaster)
 	{
 		puts("\nPOSTGRES backend interactive interface ");
-		puts("$Revision: 1.194 $ $Date: 2000/12/03 10:27:27 $\n");
+		puts("$Revision: 1.195 $ $Date: 2000/12/18 00:44:47 $\n");
 	}
 
-	/*
-	 * Initialize the deferred trigger manager
-	 */
-	if (DeferredTriggerInit() != 0)
-		goto normalexit;
-
-	SetProcessingMode(NormalProcessing);
-
 	/*
 	 * Create the memory context we will use in the main loop.
 	 *
@@ -1671,6 +1673,10 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[], const cha
 	if (sigsetjmp(Warn_restart, 1) != 0)
 	{
 		/*
+		 * NOTE: if you are tempted to add more code in this if-block,
+		 * consider the probability that it should be in AbortTransaction()
+		 * instead.
+		 *
 		 * Make sure we are in a valid memory context during recovery.
 		 *
 		 * We use ErrorContext in hopes that it will have some free space
@@ -1678,19 +1684,22 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[], const cha
 		 */
 		MemoryContextSwitchTo(ErrorContext);
 
+		/* Do the recovery */
 		if (DebugLvl >= 1)
 			elog(DEBUG, "AbortCurrentTransaction");
 		AbortCurrentTransaction();
 
-		if (ExitAfterAbort)
-			goto errorexit;
-
 		/*
-		 * If we recovered successfully, return to normal top-level context
-		 * and clear ErrorContext for next time.
+		 * Now return to normal top-level context and clear ErrorContext
+		 * for next time.
 		 */
 		MemoryContextSwitchTo(TopMemoryContext);
 		MemoryContextResetAndDeleteChildren(ErrorContext);
+
+		/*
+		 * Clear flag to indicate that we got out of error recovery mode
+		 * successfully.  (Flag was set in elog.c before longjmp().)
+		 */
 		InError = false;
 	}
 
@@ -1775,7 +1784,7 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[], const cha
 				if (HandleFunctionRequest() == EOF)
 				{
 					/* lost frontend connection during F message input */
-					goto normalexit;
+					proc_exit(0);
 				}
 
 				/* commit the function-invocation transaction */
@@ -1830,7 +1839,14 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[], const cha
 				 */
 			case 'X':
 			case EOF:
-				goto normalexit;
+				/*
+				 * NOTE: if you are tempted to add more code here, DON'T!
+				 * Whatever you had in mind to do should be set up as
+				 * an on_proc_exit or on_shmem_exit callback, instead.
+				 * Otherwise it will fail to be called during other
+				 * backend-shutdown scenarios.
+				 */
+				proc_exit(0);
 
 			default:
 				elog(ERROR, "unknown frontend message was received");
@@ -1845,16 +1861,8 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[], const cha
 #endif
 	}							/* end of input-reading loop */
 
-normalexit:
-	ExitAfterAbort = true;		/* ensure we will exit if elog during abort */
-	AbortOutOfAnyTransaction();
-	if (!IsUnderPostmaster)
-		ShutdownXLOG();
-
-errorexit:
-	pq_close();
-	ProcReleaseLocks();			/* Just to be sure... */
-	proc_exit(0);
+	/* can't get here because the above loop never exits */
+	Assert(false);
 
 	return 1;					/* keep compiler quiet */
 }
diff --git a/src/backend/utils/error/elog.c b/src/backend/utils/error/elog.c
index cb56f33c83c3942ed806e035c0ce85e1d0056a31..6a9ef98f97a34e1d825ecd0e6d4ee1e8182c7400 100644
--- a/src/backend/utils/error/elog.c
+++ b/src/backend/utils/error/elog.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/utils/error/elog.c,v 1.73 2000/12/06 17:25:46 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/utils/error/elog.c,v 1.74 2000/12/18 00:44:47 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -159,7 +159,7 @@ elog(int lev, const char *fmt, ...)
 		/* this is probably redundant... */
 		if (IsInitProcessingMode())
 			lev = FATAL;
-		if (StopIfError)
+		if (CritSectionCount > 0)
 			lev = STOP;
 	}
 
@@ -445,21 +445,26 @@ elog(int lev, const char *fmt, ...)
 	{
 
 		/*
+		 * For a FATAL error, we let proc_exit clean up and exit.
+		 *
 		 * If we have not yet entered the main backend loop (ie, we are in
-		 * the postmaster or in backend startup), then go directly to
+		 * the postmaster or in backend startup), we also go directly to
 		 * proc_exit.  The same is true if anyone tries to report an error
 		 * after proc_exit has begun to run.  (It's proc_exit's
 		 * responsibility to see that this doesn't turn into infinite
 		 * recursion!)	But in the latter case, we exit with nonzero exit
 		 * code to indicate that something's pretty wrong.
 		 */
-		if (proc_exit_inprogress || !Warn_restart_ready)
+		if (lev == FATAL || !Warn_restart_ready || proc_exit_inprogress)
 		{
+			/*
+			 * fflush here is just to improve the odds that we get to see
+			 * the error message, in case things are so hosed that proc_exit
+			 * crashes.  Any other code you might be tempted to add here
+			 * should probably be in an on_proc_exit callback instead.
+			 */
 			fflush(stdout);
 			fflush(stderr);
-			ProcReleaseSpins(NULL);		/* get rid of spinlocks we hold */
-			ProcReleaseLocks(); /* get rid of real locks we hold */
-			/* XXX shouldn't proc_exit be doing the above?? */
 			proc_exit((int) proc_exit_inprogress);
 		}
 
@@ -471,13 +476,8 @@ elog(int lev, const char *fmt, ...)
 		InError = true;
 
 		/*
-		 * Otherwise we can return to the main loop in postgres.c. In the
-		 * FATAL case, postgres.c will call proc_exit, but not till after
-		 * completing a standard transaction-abort sequence.
+		 * Otherwise we can return to the main loop in postgres.c.
 		 */
-		ProcReleaseSpins(NULL); /* get rid of spinlocks we hold */
-		if (lev == FATAL)
-			ExitAfterAbort = true;
 		siglongjmp(Warn_restart, 1);
 	}
 
diff --git a/src/backend/utils/init/postinit.c b/src/backend/utils/init/postinit.c
index f213e561c1bc8f08fd5c91e47d4666c965fb2608..c8bd8a0d26687ca7d0705967cf848e3d88edd343 100644
--- a/src/backend/utils/init/postinit.c
+++ b/src/backend/utils/init/postinit.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/utils/init/postinit.c,v 1.75 2000/12/14 23:51:35 wieck Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/utils/init/postinit.c,v 1.76 2000/12/18 00:44:48 tgl Exp $
  *
  *
  *-------------------------------------------------------------------------
@@ -28,6 +28,7 @@
 #include "access/heapam.h"
 #include "catalog/catname.h"
 #include "catalog/pg_database.h"
+#include "commands/trigger.h"
 #include "miscadmin.h"
 #include "storage/backendid.h"
 #include "storage/proc.h"
@@ -37,6 +38,7 @@
 #include "utils/portal.h"
 #include "utils/relcache.h"
 #include "utils/syscache.h"
+#include "utils/temprel.h"
 
 #ifdef MULTIBYTE
 #include "mb/pg_wchar.h"
@@ -44,6 +46,9 @@
 
 static void ReverifyMyDatabase(const char *name);
 static void InitCommunication(void);
+static void ShutdownPostgres(void);
+
+int			lockingOff = 0;		/* backend -L switch */
 
 
 /*** InitPostgres support ***/
@@ -115,12 +120,8 @@ ReverifyMyDatabase(const char *name)
 	 */
 	dbform = (Form_pg_database) GETSTRUCT(tup);
 	if (! dbform->datallowconn)
-	{
-		heap_endscan(pgdbscan);
-		heap_close(pgdbrel, AccessShareLock);
 		elog(FATAL, "Database \"%s\" is not currently accepting connections",
 			 name);
-	}
 
 	/*
 	 * OK, we're golden.  Only other to-do item is to save the MULTIBYTE
@@ -163,6 +164,28 @@ InitCommunication(void)
 }
 
 
+/*
+ * Early initialization of a backend (either standalone or under postmaster).
+ * This happens even before InitPostgres.
+ */
+void
+BaseInit(void)
+{
+	/*
+	 * Attach to shared memory and semaphores, and initialize our
+	 * input/output/debugging file descriptors.
+	 */
+	InitCommunication();
+	DebugFileOpen();
+
+	/* Do local initialization of storage and buffer managers */
+	smgrinit();
+	InitBufferPoolAccess();
+	InitLocalBuffer();
+
+	EnablePortalManager();		/* memory for portal/transaction stuff */
+}
+
 
 /* --------------------------------
  * InitPostgres
@@ -172,16 +195,13 @@ InitCommunication(void)
  *		Be very careful with the order of calls in the InitPostgres function.
  * --------------------------------
  */
-int			lockingOff = 0;		/* backend -L switch */
-
-/*
- */
 void
 InitPostgres(const char *dbname, const char *username)
 {
 	bool		bootstrap = IsBootstrapProcessingMode();
 
 	SetDatabaseName(dbname);
+
 	/* ----------------
 	 *	initialize the database id used for system caches and lock tables
 	 * ----------------
@@ -299,6 +319,12 @@ InitPostgres(const char *dbname, const char *username)
 	 */
 	InitCatalogCache();
 
+	/*
+	 * Initialize the deferred trigger manager --- must happen before
+	 * first transaction start.
+	 */
+	DeferredTriggerInit();
+
 	/* start a new transaction here before access to db */
 	if (!bootstrap)
 		StartTransactionCommand();
@@ -322,27 +348,62 @@ InitPostgres(const char *dbname, const char *username)
 
 	/*
 	 * Unless we are bootstrapping, double-check that InitMyDatabaseInfo()
-	 * got a correct result.  We can't do this until essentially all the
-	 * infrastructure is up, so just do it at the end.
+	 * got a correct result.  We can't do this until all the database-access
+	 * infrastructure is up.
 	 */
 	if (!bootstrap)
 		ReverifyMyDatabase(dbname);
-}
 
-void
-BaseInit(void)
-{
+#ifdef MULTIBYTE
+	/* set default client encoding --- uses info from ReverifyMyDatabase */
+	set_default_client_encoding();
+#endif
+
 	/*
-	 * Attach to shared memory and semaphores, and initialize our
-	 * input/output/debugging file descriptors.
+	 * Set up process-exit callbacks to remove temp relations and then
+	 * do pre-shutdown cleanup.  This should be last because we want
+	 * shmem_exit to call these routines before the exit callbacks that
+	 * are registered by buffer manager, lock manager, etc.  We need
+	 * to run this code before we close down database access!
 	 */
-	InitCommunication();
-	DebugFileOpen();
-
-	smgrinit();
+	on_shmem_exit(ShutdownPostgres, 0);
+	/* because callbacks are called in reverse order, this gets done first: */
+	on_shmem_exit(remove_all_temp_relations, 0);
 
-	EnablePortalManager();		/* memory for portal/transaction stuff */
+	/* close the transaction we started above */
+	if (!bootstrap)
+		CommitTransactionCommand();
+}
 
-	/* initialize the local buffer manager */
-	InitLocalBuffer();
+/*
+ * Backend-shutdown callback.  Do cleanup that we want to be sure happens
+ * before all the supporting modules begin to nail their doors shut via
+ * their own callbacks.  Note that because this has to be registered very
+ * late in startup, it will not get called if we suffer a failure *during*
+ * startup.
+ *
+ * User-level cleanup, such as temp-relation removal and UNLISTEN, happens
+ * via separate callbacks that execute before this one.  We don't combine the
+ * callbacks because we still want this one to happen if the user-level
+ * cleanup fails.
+ */
+static void
+ShutdownPostgres(void)
+{
+	/*
+	 * These operations are really just a minimal subset of AbortTransaction().
+	 * We don't want to do any inessential cleanup, since that just raises
+	 * the odds of failure --- but there's some stuff we need to do.
+	 *
+	 * Release any spinlocks that we may hold.  This is a kluge to improve
+	 * the odds that we won't get into a self-made stuck spinlock scenario
+	 * while trying to shut down.
+	 */
+	ProcReleaseSpins(NULL);
+	/*
+	 * In case a transaction is open, delete any files it created.  This
+	 * has to happen before bufmgr shutdown, so having smgr register a
+	 * callback for it wouldn't work.
+	 */
+	smgrDoPendingDeletes(false); /* delete as though aborting xact */
 }
diff --git a/src/include/access/xlog.h b/src/include/access/xlog.h
index 269315dc78ecbd4789525316e841ef9ad70d0075..1c10501fb7d5fc151194fda407853cd2937cfe43 100644
--- a/src/include/access/xlog.h
+++ b/src/include/access/xlog.h
@@ -3,7 +3,7 @@
  *
  * PostgreSQL transaction log manager
  *
- * $Header: /cvsroot/pgsql/src/include/access/xlog.h,v 1.13 2000/12/03 10:27:28 vadim Exp $
+ * $Header: /cvsroot/pgsql/src/include/access/xlog.h,v 1.14 2000/12/18 00:44:48 tgl Exp $
  */
 #ifndef XLOG_H
 #define XLOG_H
@@ -88,7 +88,7 @@ typedef XLogPageHeaderData *XLogPageHeader;
 extern	StartUpID	ThisStartUpID;	/* current SUI */
 extern	bool		InRecovery;
 extern	XLogRecPtr	MyLastRecPtr;
-extern	uint32		StopIfError;
+extern	uint32		CritSectionCount;
 
 typedef struct RmgrData
 {
diff --git a/src/include/commands/trigger.h b/src/include/commands/trigger.h
index 22dac3f5fe34232527b6936c1854ef8b037889dc..c9fbcae54a35d65fab184389f2a886f1bfd36ed3 100644
--- a/src/include/commands/trigger.h
+++ b/src/include/commands/trigger.h
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: trigger.h,v 1.21 2000/06/08 22:37:42 momjian Exp $
+ * $Id: trigger.h,v 1.22 2000/12/18 00:44:48 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -129,7 +129,7 @@ typedef struct DeferredTriggerEventData
 typedef struct DeferredTriggerEventData *DeferredTriggerEvent;
 
 
-extern int	DeferredTriggerInit(void);
+extern void DeferredTriggerInit(void);
 extern void DeferredTriggerBeginXact(void);
 extern void DeferredTriggerEndQuery(void);
 extern void DeferredTriggerEndXact(void);
diff --git a/src/include/libpq/libpq.h b/src/include/libpq/libpq.h
index c86862317c82ac05395d10994c3828f7a8582905..a8deb15eee20c15e7702021640546147c92024cf 100644
--- a/src/include/libpq/libpq.h
+++ b/src/include/libpq/libpq.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: libpq.h,v 1.41 2000/11/14 01:15:04 momjian Exp $
+ * $Id: libpq.h,v 1.42 2000/12/18 00:44:49 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -60,7 +60,6 @@ extern int	StreamServerPort(int family, char *hostName,
 extern int	StreamConnection(int server_fd, Port *port);
 extern void StreamClose(int sock);
 extern void pq_init(void);
-extern void pq_close(void);
 extern int	pq_getbytes(char *s, size_t len);
 extern int	pq_getstring(StringInfo s);
 extern int	pq_peekbyte(void);
diff --git a/src/include/storage/bufmgr.h b/src/include/storage/bufmgr.h
index 27bcc090ed9d449ac8b54905c8a90b35e26ef674..7f1906441a8ba7595d850afd90c4ca1325cf585b 100644
--- a/src/include/storage/bufmgr.h
+++ b/src/include/storage/bufmgr.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: bufmgr.h,v 1.46 2000/11/30 08:46:26 vadim Exp $
+ * $Id: bufmgr.h,v 1.47 2000/12/18 00:44:49 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -168,6 +168,7 @@ extern Buffer ReleaseAndReadBuffer(Buffer buffer, Relation relation,
 extern int	FlushBuffer(Buffer buffer, bool sync, bool release);
 
 extern void InitBufferPool(void);
+extern void InitBufferPoolAccess(void);
 extern void PrintBufferUsage(FILE *statfp);
 extern void ResetBufferUsage(void);
 extern void ResetBufferPool(bool isCommit);
diff --git a/src/include/utils/elog.h b/src/include/utils/elog.h
index acb820497309d4fea4ba2f876c84fc583a18c57c..37db2c7aaf84c5e3025af0805f40dd90606fb4d1 100644
--- a/src/include/utils/elog.h
+++ b/src/include/utils/elog.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: elog.h,v 1.20 2000/12/06 17:25:45 tgl Exp $
+ * $Id: elog.h,v 1.21 2000/12/18 00:44:50 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -28,24 +28,24 @@ extern int Use_syslog;
 #endif
 
 /*
- * If StopIfError > 0 signal handlers mustn't do
+ * If CritSectionCount > 0, signal handlers mustn't do
  * elog(ERROR|FATAL), instead remember what action is
- * required with QueryCancel & ExitAfterAbort.
+ * required with QueryCancel & ProcDiePending.
  */
-extern uint32 StopIfError;		/* duplicates access/xlog.h */
+extern uint32 CritSectionCount;	/* duplicates access/xlog.h */
 extern bool QueryCancel;		/* duplicates miscadmin.h */
-extern bool	ExitAfterAbort;
+extern bool	ProcDiePending;
 
-#define	START_CRIT_CODE		(StopIfError++)
+#define	START_CRIT_CODE		(CritSectionCount++)
 
 #define END_CRIT_CODE	\
 	do { \
-		if (!StopIfError) \
+		if (CritSectionCount == 0) \
 			elog(STOP, "Not in critical section"); \
-		StopIfError--; \
-		if (!StopIfError && QueryCancel) \
+		CritSectionCount--; \
+		if (CritSectionCount == 0 && QueryCancel) \
 		{ \
-			if (ExitAfterAbort) \
+			if (ProcDiePending) \
 				elog(FATAL, "The system is shutting down"); \
 			else \
 				elog(ERROR, "Query was cancelled."); \