]> granicus.if.org Git - postgresql/commitdiff
On further consideration, there's another problem here: the existing
authorTom Lane <tgl@sss.pgh.pa.us>
Sun, 5 Sep 2004 03:42:13 +0000 (03:42 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Sun, 5 Sep 2004 03:42:13 +0000 (03:42 +0000)
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
src/include/utils/elog.h

index 01df39a6191759441c099d35fa3c2ecf21d8efaa..ded96313c330cd71c8ba229a88fca2bb56be32d4 100644 (file)
@@ -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;
index 98bea52eb94960ff4763825c2ea4c6a75324491a..456c2aa9317dae72a925a66609a55032c2ac09b8 100644 (file)
@@ -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