From e1492cc34ca7bd31ba8ed30f8638b33bc28ae3fd Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Tue, 16 Nov 1999 06:13:36 +0000
Subject: [PATCH] Modify elog() logic so that it won't try to
 longjmp(Warn_restart) before Warn_restart has been set by the backend main
 loop.  This means that elog(ERROR) or elog(FATAL) in the postmaster or during
 backend startup now have well-defined behavior: proc_exit() rather than
 coredump. In the case of elog() inside the postmaster, I think that
 proc_exit() is probably not enough --- don't we want our child backends to be
 forced to quit too?  But I don't understand Vadim's recent changes in this
 area, so I'll leave it to him to look over and tweak if needed.

---
 src/backend/tcop/postgres.c    | 19 +++++++++++--------
 src/backend/utils/error/elog.c | 14 +++++++++-----
 src/include/tcop/tcopprot.h    |  3 ++-
 3 files changed, 22 insertions(+), 14 deletions(-)

diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index a73344e932a..619a9d9ba14 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.136 1999/10/25 03:07:48 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.137 1999/11/16 06:13:35 tgl Exp $
  *
  * NOTES
  *	  this is the "main" module of the postgres backend and
@@ -116,6 +116,7 @@ static bool IsEmptyQuery = false;
 /* note: these declarations had better match tcopprot.h */
 DLLIMPORT sigjmp_buf Warn_restart;
 
+bool		Warn_restart_ready = false;
 bool		InError = false;
 bool		ExitAfterAbort = false;
 
@@ -748,7 +749,7 @@ pg_exec_query_dest(char *query_string,	/* string to execute */
  *		Some backend has bought the farm,
  *		so we need to stop what we're doing and exit.
  *
- *		die() performs an orderly cleanup via ExitPostgres()
+ *		die() performs an orderly cleanup via proc_exit()
  * --------------------------------
  */
 
@@ -771,7 +772,7 @@ quickdie(SIGNAL_ARGS)
 
 
 	/*
-	 * DO NOT ExitPostgres(0) -- we're here because shared memory may be
+	 * DO NOT proc_exit(0) -- we're here because shared memory may be
 	 * corrupted, so we don't want to flush any shared state to stable
 	 * storage.  Just nail the windows shut and get out of town.
 	 */
@@ -1494,14 +1495,16 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[])
 	if (!IsUnderPostmaster)
 	{
 		puts("\nPOSTGRES backend interactive interface ");
-		puts("$Revision: 1.136 $ $Date: 1999/10/25 03:07:48 $\n");
+		puts("$Revision: 1.137 $ $Date: 1999/11/16 06:13:35 $\n");
 	}
 
 	/*
 	 * Initialize the deferred trigger manager
 	 */
 	if (DeferredTriggerInit() != 0)
-		ExitPostgres(1);
+		proc_exit(1);
+
+	SetProcessingMode(NormalProcessing);
 
 	/*
 	 * POSTGRES main processing loop begins here
@@ -1510,8 +1513,6 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[])
 	 * so we abort the current transaction and start a new one.
 	 */
 
-	SetProcessingMode(NormalProcessing);
-
 	if (sigsetjmp(Warn_restart, 1) != 0)
 	{
 		time(&tim);
@@ -1524,10 +1525,12 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[])
 		if (ExitAfterAbort)
 		{
 			ProcReleaseLocks();		/* Just to be sure... */
-			ExitPostgres(0);
+			proc_exit(0);
 		}
 	}
 
+	Warn_restart_ready = true;	/* we can now handle elog(ERROR) */
+
 	PG_SETMASK(&UnBlockSig);
 
 	/*
diff --git a/src/backend/utils/error/elog.c b/src/backend/utils/error/elog.c
index 247cf1c724a..b8da26779b6 100644
--- a/src/backend/utils/error/elog.c
+++ b/src/backend/utils/error/elog.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/utils/error/elog.c,v 1.50 1999/10/25 03:07:50 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/utils/error/elog.c,v 1.51 1999/11/16 06:13:36 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -378,12 +378,13 @@ elog(int lev, const char *fmt, ...)
 		}
 		InError = true;
 		ProcReleaseSpins(NULL); /* get rid of spinlocks we hold */
-		if (lev == FATAL)
+		if (! Warn_restart_ready)
 		{
-			if (IsInitProcessingMode())
-				ExitPostgres(0);
-			ExitAfterAbort = true;
+			/* error reported before there is a main loop to return to */
+			elog(REALLYFATAL, "elog: error in postmaster or backend startup, giving up!");
 		}
+		if (lev == FATAL)
+			ExitAfterAbort = true;
 		/* exit to main loop */
 		siglongjmp(Warn_restart, 1);
 	}
@@ -393,6 +394,9 @@ elog(int lev, const char *fmt, ...)
 		/*
 		 * Serious crash time. Postmaster will observe nonzero
 		 * process exit status and kill the other backends too.
+		 *
+		 * XXX: what if we are *in* the postmaster?  proc_exit()
+		 * won't kill our children...
 		 */
 		fflush(stdout);
 		fflush(stderr);
diff --git a/src/include/tcop/tcopprot.h b/src/include/tcop/tcopprot.h
index 65bad2234e3..03d68f0c308 100644
--- a/src/include/tcop/tcopprot.h
+++ b/src/include/tcop/tcopprot.h
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: tcopprot.h,v 1.22 1999/10/06 21:58:18 vadim Exp $
+ * $Id: tcopprot.h,v 1.23 1999/11/16 06:13:34 tgl Exp $
  *
  * OLD COMMENTS
  *	  This file was created so that other c files could get the two
@@ -37,6 +37,7 @@
 #define siglongjmp longjmp
 #endif
 extern DLLIMPORT sigjmp_buf Warn_restart;
+extern bool Warn_restart_ready;
 extern bool InError;
 extern bool	ExitAfterAbort;
 
-- 
GitLab