diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index 1a71378a2e342f5f756eb3f7580d1a4594d09183..3cb9e2938e8fae4a5a07685443184a063b6bb4bf 100644
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -28,7 +28,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.220 2001/06/14 19:59:24 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.221 2001/06/16 22:58:12 tgl Exp $
  *
  * NOTES
  *
@@ -1280,8 +1280,16 @@ canAcceptConnections(void)
 		return "The Data Base System is starting up";
 	if (FatalError)
 		return "The Data Base System is in recovery mode";
-	/* Can't start backend if max backend count is exceeded. */
-	if (CountChildren() >= MaxBackends)
+	/*
+	 * Don't start too many children.
+	 *
+	 * We allow more connections than we can have backends here because
+	 * some might still be authenticating; they might fail auth, or some
+	 * existing backend might exit before the auth cycle is completed.
+	 * The exact MaxBackends limit is enforced when a new backend tries
+	 * to join the shared-inval backend array.
+	 */
+	if (CountChildren() >= 2 * MaxBackends)
 		return "Sorry, too many clients already";
 
 	return NULL;
@@ -1738,12 +1746,6 @@ CleanupProc(int pid,
 				GetRedoRecPtr();
 			}
 		}
-		else
-		{
-			/* Why is this done here, and not by the backend itself? */
-			if (!FatalError)
-				ProcRemove(pid);
-		}
 
 		return;
 	}
@@ -1765,7 +1767,6 @@ CleanupProc(int pid,
 		bp = (Backend *) DLE_VAL(curr);
 		if (bp->pid != pid)
 		{
-
 			/*
 			 * This backend is still alive.  Unless we did so already,
 			 * tell it to commit hara-kiri.
@@ -1786,13 +1787,8 @@ CleanupProc(int pid,
 		}
 		else
 		{
-
 			/*
 			 * Found entry for freshly-dead backend, so remove it.
-			 *
-			 * Don't call ProcRemove() here, since shmem may be corrupted! We
-			 * are going to reinitialize shmem and semaphores anyway once
-			 * all the children are dead, so no need for it.
 			 */
 			DLRemove(curr);
 			free(bp);
diff --git a/src/backend/storage/ipc/sinval.c b/src/backend/storage/ipc/sinval.c
index d60e6198f51334bc138177eb0f8bc79c4fbd9e93..9177a81604b894b7efd8b8e6023129caf7d7c7ae 100644
--- a/src/backend/storage/ipc/sinval.c
+++ b/src/backend/storage/ipc/sinval.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/storage/ipc/sinval.c,v 1.32 2001/06/01 20:07:16 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/storage/ipc/sinval.c,v 1.33 2001/06/16 22:58:13 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -43,13 +43,15 @@ CreateSharedInvalidationState(int maxBackends)
 void
 InitBackendSharedInvalidationState(void)
 {
+	int		flag;
+
 	SpinAcquire(SInvalLock);
-	if (!SIBackendInit(shmInvalBuffer))
-	{
-		SpinRelease(SInvalLock);
-		elog(FATAL, "Backend cache invalidation initialization failed");
-	}
+	flag = SIBackendInit(shmInvalBuffer);
 	SpinRelease(SInvalLock);
+	if (flag < 0)				/* unexpected problem */
+		elog(FATAL, "Backend cache invalidation initialization failed");
+	if (flag == 0)				/* expected problem: MaxBackends exceeded */
+		elog(FATAL, "Sorry, too many clients already");
 }
 
 /*
diff --git a/src/backend/storage/ipc/sinvaladt.c b/src/backend/storage/ipc/sinvaladt.c
index 06ba354d94a2ea4b9c11ba71da0fe096985e12bb..63bc037bc9a5d3db5b5a17578c5e0838cadd40c9 100644
--- a/src/backend/storage/ipc/sinvaladt.c
+++ b/src/backend/storage/ipc/sinvaladt.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/storage/ipc/sinvaladt.c,v 1.38 2001/03/22 03:59:45 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/storage/ipc/sinvaladt.c,v 1.39 2001/06/16 22:58:15 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -79,6 +79,11 @@ SIBufferInit(int maxBackends)
  * SIBackendInit
  *		Initialize a new backend to operate on the sinval buffer
  *
+ * Returns:
+ *	   >0	A-OK
+ *		0	Failed to find a free procState slot (ie, MaxBackends exceeded)
+ *	   <0	Some other failure (not currently used)
+ *
  * NB: this routine, and all following ones, must be executed with the
  * SInvalLock spinlock held, since there may be multiple backends trying
  * to access the buffer.
@@ -109,12 +114,7 @@ SIBackendInit(SISeg *segP)
 		}
 		else
 		{
-
-			/*
-			 * elog() with spinlock held is probably not too cool, but
-			 * this condition should never happen anyway.
-			 */
-			elog(NOTICE, "SIBackendInit: no free procState slot available");
+			/* out of procState slots */
 			MyBackendId = InvalidBackendId;
 			return 0;
 		}
diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c
index e64d3886aa46865f38a8a984599490c170787417..d2a8fe10df845ea74d7b64bda8a807db98c42542 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.102 2001/05/25 15:45:33 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/storage/lmgr/proc.c,v 1.103 2001/06/16 22:58:16 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -390,45 +390,16 @@ ProcReleaseLocks(bool isCommit)
 				   !isCommit, GetCurrentTransactionId());
 }
 
-/*
- * ProcRemove -
- *	  called by the postmaster to clean up the global tables after a
- *	  backend exits.  This also frees up the proc's wait semaphore.
- */
-bool
-ProcRemove(int pid)
-{
-	SHMEM_OFFSET location;
-	PROC	   *proc;
-
-	location = ShmemPIDDestroy(pid);
-	if (location == INVALID_OFFSET)
-		return FALSE;
-	proc = (PROC *) MAKE_PTR(location);
-
-	SpinAcquire(ProcStructLock);
-
-	ProcFreeSem(proc->sem.semId, proc->sem.semNum);
-
-	/* Add PROC struct to freelist so space can be recycled in future */
-	proc->links.next = ProcGlobal->freeProcs;
-	ProcGlobal->freeProcs = MAKE_OFFSET(proc);
-
-	SpinRelease(ProcStructLock);
-
-	return TRUE;
-}
 
 /*
  * ProcKill() -- Destroy the per-proc data structure for
  *		this process. Release any of its held spin locks.
- *
- * This is done inside the backend process before it exits.
- * ProcRemove, above, will be done by the postmaster afterwards.
  */
 static void
 ProcKill(void)
 {
+	SHMEM_OFFSET location;
+
 	Assert(MyProc);
 
 	/* Release any spinlocks I am holding */
@@ -445,9 +416,26 @@ ProcKill(void)
 	LockReleaseAll(USER_LOCKMETHOD, MyProc, true, InvalidTransactionId);
 #endif
 
+	/* Remove my PROC struct from the shmem hash table */
+	location = ShmemPIDDestroy(MyProcPid);
+	Assert(location != INVALID_OFFSET);
+	Assert(MyProc == (PROC *) MAKE_PTR(location));
+
+	SpinAcquire(ProcStructLock);
+
+	/* Free up my wait semaphore */
+	ProcFreeSem(MyProc->sem.semId, MyProc->sem.semNum);
+
+	/* Add PROC struct to freelist so space can be recycled in future */
+	MyProc->links.next = ProcGlobal->freeProcs;
+	ProcGlobal->freeProcs = MAKE_OFFSET(MyProc);
+
+	SpinRelease(ProcStructLock);
+
 	MyProc = NULL;
 }
 
+
 /*
  * ProcQueue package: routines for putting processes to sleep
  *		and  waking them up
diff --git a/src/backend/utils/init/postinit.c b/src/backend/utils/init/postinit.c
index c3c3ad946ec4880f4eedeef19a394fad7730dcb0..dedd9a8e7654dde06ac98eb06df6ad5bf15357da 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.86 2001/05/30 20:52:32 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/utils/init/postinit.c,v 1.87 2001/06/16 22:58:16 tgl Exp $
  *
  *
  *-------------------------------------------------------------------------
@@ -148,13 +148,11 @@ ReverifyMyDatabase(const char *name)
 static void
 InitCommunication(void)
 {
-
 	/*
 	 * initialize shared memory and semaphores appropriately.
 	 */
 	if (!IsUnderPostmaster)		/* postmaster already did this */
 	{
-
 		/*
 		 * we're running a postgres backend by itself with no front end or
 		 * postmaster.	Create private "shmem" and semaphores.	Setting
@@ -168,11 +166,16 @@ InitCommunication(void)
 /*
  * Early initialization of a backend (either standalone or under postmaster).
  * This happens even before InitPostgres.
+ *
+ * If you're wondering why this is separate from InitPostgres at all:
+ * the critical distinction is that this stuff has to happen before we can
+ * run XLOG-related initialization, which is done before InitPostgres --- in
+ * fact, for cases such as checkpoint creation processes, InitPostgres may
+ * never be done at all.
  */
 void
 BaseInit(void)
 {
-
 	/*
 	 * Attach to shared memory and semaphores, and initialize our
 	 * input/output/debugging file descriptors.
@@ -184,8 +187,6 @@ BaseInit(void)
 	smgrinit();
 	InitBufferPoolAccess();
 	InitLocalBuffer();
-
-	EnablePortalManager();		/* memory for portal/transaction stuff */
 }
 
 
@@ -202,16 +203,18 @@ InitPostgres(const char *dbname, const char *username)
 {
 	bool		bootstrap = IsBootstrapProcessingMode();
 
-	SetDatabaseName(dbname);
-
 	/*
-	 * initialize the database id used for system caches and lock tables
+	 * Set up the global variables holding database name, id, and path.
+	 *
+	 * We take a shortcut in the bootstrap case, otherwise we have to look up
+	 * the db name in pg_database.
 	 */
+	SetDatabaseName(dbname);
+
 	if (bootstrap)
 	{
 		MyDatabaseId = TemplateDbOid;
 		SetDatabasePath(GetDatabasePath(MyDatabaseId));
-		LockDisable(true);
 	}
 	else
 	{
@@ -259,6 +262,28 @@ InitPostgres(const char *dbname, const char *username)
 	 * Code after this point assumes we are in the proper directory!
 	 */
 
+	/*
+	 * Set up my per-backend PROC struct in shared memory.  (We need to
+	 * know MyDatabaseId before we can do this, since it's entered into
+	 * the PROC struct.)
+	 */
+	InitProcess();
+
+	/*
+	 * Initialize my entry in the shared-invalidation manager's array of
+	 * per-backend data.  (Formerly this came before InitProcess, but now
+	 * it must happen after, because it uses MyProc.)  Once I have done
+	 * this, I am visible to other backends!
+	 *
+	 * Sets up MyBackendId, a unique backend identifier.
+	 */
+	MyBackendId = InvalidBackendId;
+
+	InitBackendSharedInvalidationState();
+
+	if (MyBackendId > MAXBACKENDS || MyBackendId <= 0)
+		elog(FATAL, "InitPostgres: bad backend id %d", MyBackendId);
+
 	/*
 	 * Initialize the transaction system and the relation descriptor
 	 * cache. Note we have to make certain the lock manager is off while
@@ -281,26 +306,6 @@ InitPostgres(const char *dbname, const char *username)
 
 	LockDisable(false);
 
-	/*
-	 * Set up my per-backend PROC struct in shared memory.
-	 */
-	InitProcess();
-
-	/*
-	 * Initialize my entry in the shared-invalidation manager's array of
-	 * per-backend data.  (Formerly this came before InitProcess, but now
-	 * it must happen after, because it uses MyProc.)  Once I have done
-	 * this, I am visible to other backends!
-	 *
-	 * Sets up MyBackendId, a unique backend identifier.
-	 */
-	MyBackendId = InvalidBackendId;
-
-	InitBackendSharedInvalidationState();
-
-	if (MyBackendId > MAXBACKENDS || MyBackendId <= 0)
-		elog(FATAL, "cinit2: bad backend id %d", MyBackendId);
-
 	/*
 	 * Initialize the access methods. Does not touch files (?) - thomas
 	 * 1997-11-01
@@ -315,6 +320,9 @@ InitPostgres(const char *dbname, const char *username)
 	 */
 	InitCatalogCache();
 
+	/* Initialize portal manager */
+	EnablePortalManager();
+
 	/*
 	 * Initialize the deferred trigger manager --- must happen before
 	 * first transaction start.
diff --git a/src/include/storage/proc.h b/src/include/storage/proc.h
index 8118cf0e5cecbfbea95ae953b2f7b81b8503c1cb..a35c8f4481ecfd4fa8d5ce7ed310af91705f188a 100644
--- a/src/include/storage/proc.h
+++ b/src/include/storage/proc.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: proc.h,v 1.43 2001/05/25 15:45:34 momjian Exp $
+ * $Id: proc.h,v 1.44 2001/06/16 22:58:17 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -129,7 +129,6 @@ typedef struct procglobal
 extern void InitProcGlobal(int maxBackends);
 extern void InitProcess(void);
 extern void ProcReleaseLocks(bool isCommit);
-extern bool ProcRemove(int pid);
 
 extern void ProcQueueInit(PROC_QUEUE *queue);
 extern int ProcSleep(LOCKMETHODTABLE *lockMethodTable, LOCKMODE lockmode,