From 1a86e6eabfd02cec1253a7eaf8a5f859193388ad Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Sun, 5 Sep 2004 03:42:13 +0000
Subject: [PATCH] On further consideration, there's another problem here: the
 existing elog() emulation code always calls errstart with ERROR error level.
 This means that a recursive error call triggered by elog would do
 MemoryContextReset(ErrorContext), whether or not this was actually
 appropriate.  I'm surprised we haven't seen this in the field...

---
 src/backend/utils/error/elog.c | 43 +++++++++++++++++++++++++++++-----
 src/include/utils/elog.h       |  5 ++--
 2 files changed, 40 insertions(+), 8 deletions(-)

diff --git a/src/backend/utils/error/elog.c b/src/backend/utils/error/elog.c
index 01df39a6191..ded96313c33 100644
--- a/src/backend/utils/error/elog.c
+++ b/src/backend/utils/error/elog.c
@@ -42,7 +42,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/utils/error/elog.c,v 1.149 2004/09/05 02:01:41 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/utils/error/elog.c,v 1.150 2004/09/05 03:42:11 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -862,10 +862,42 @@ getinternalerrposition(void)
 
 
 /*
- * elog_finish --- finish up for old-style API
+ * elog_start --- startup for old-style API
+ *
+ * All that we do here is stash the hidden filename/lineno/funcname
+ * arguments into a stack entry.
  *
- * The elog() macro already called errstart, but with ERROR rather than
- * the true elevel.
+ * We need this to be separate from elog_finish because there's no other
+ * portable way to deal with inserting extra arguments into the elog call.
+ * (If macros with variable numbers of arguments were portable, it'd be
+ * easy, but they aren't.)
+ */
+void
+elog_start(const char *filename, int lineno, const char *funcname)
+{
+	ErrorData  *edata;
+
+	if (++errordata_stack_depth >= ERRORDATA_STACK_SIZE)
+	{
+		/*
+		 * Wups, stack not big enough.	We treat this as a PANIC condition
+		 * because it suggests an infinite loop of errors during error
+		 * recovery.
+		 */
+		errordata_stack_depth = -1;		/* make room on stack */
+		ereport(PANIC, (errmsg_internal("ERRORDATA_STACK_SIZE exceeded")));
+	}
+
+	edata = &errordata[errordata_stack_depth];
+	edata->filename = filename;
+	edata->lineno = lineno;
+	edata->funcname = funcname;
+	/* errno is saved now so that error parameter eval can't change it */
+	edata->saved_errno = errno;
+}
+
+/*
+ * elog_finish --- finish up for old-style API
  */
 void
 elog_finish(int elevel, const char *fmt,...)
@@ -876,8 +908,7 @@ elog_finish(int elevel, const char *fmt,...)
 	CHECK_STACK_DEPTH();
 
 	/*
-	 * We need to redo errstart() because the elog macro had to call it
-	 * with bogus elevel.
+	 * Do errstart() to see if we actually want to report the message.
 	 */
 	errordata_stack_depth--;
 	errno = edata->saved_errno;
diff --git a/src/include/utils/elog.h b/src/include/utils/elog.h
index 98bea52eb94..456c2aa9317 100644
--- a/src/include/utils/elog.h
+++ b/src/include/utils/elog.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2004, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/utils/elog.h,v 1.75 2004/08/29 05:06:58 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/utils/elog.h,v 1.76 2004/09/05 03:42:13 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -153,8 +153,9 @@ extern int	getinternalerrposition(void);
  *		elog(ERROR, "portal \"%s\" not found", stmt->portalname);
  *----------
  */
-#define elog	errstart(ERROR, __FILE__, __LINE__, PG_FUNCNAME_MACRO), elog_finish
+#define elog	elog_start(__FILE__, __LINE__, PG_FUNCNAME_MACRO), elog_finish
 
+extern void elog_start(const char *filename, int lineno, const char *funcname);
 extern void
 elog_finish(int elevel, const char *fmt,...)
 /* This extension allows gcc to check the format string for consistency with
-- 
GitLab