summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/utils/error/elog.c17
-rw-r--r--src/backend/utils/misc/guc.c10
2 files changed, 18 insertions, 9 deletions
diff --git a/src/backend/utils/error/elog.c b/src/backend/utils/error/elog.c
index b7b9692f8c8..648d2d2e70c 100644
--- a/src/backend/utils/error/elog.c
+++ b/src/backend/utils/error/elog.c
@@ -542,11 +542,20 @@ errfinish(const char *filename, int lineno, const char *funcname)
/* Emit the message to the right places */
EmitErrorReport();
- /* Now free up subsidiary data attached to stack entry, and release it */
- FreeErrorDataContents(edata);
- errordata_stack_depth--;
+ /*
+ * If this is the outermost recursion level, we can clean up by resetting
+ * ErrorContext altogether (compare FlushErrorState), which is good
+ * because it cleans up any random leakages that might have occurred in
+ * places such as context callback functions. If we're nested, we can
+ * only safely remove the subsidiary data of the current stack entry.
+ */
+ if (errordata_stack_depth == 0 && recursion_depth == 1)
+ MemoryContextReset(ErrorContext);
+ else
+ FreeErrorDataContents(edata);
- /* Exit error-handling context */
+ /* Release stack entry and exit error-handling context */
+ errordata_stack_depth--;
MemoryContextSwitchTo(oldcontext);
recursion_depth--;
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 107b5a273a2..8794e26ef1d 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -6849,7 +6849,7 @@ call_bool_check_hook(struct config_bool *conf, bool *newval, void **extra,
errdetail_internal("%s", GUC_check_errdetail_string) : 0,
GUC_check_errhint_string ?
errhint("%s", GUC_check_errhint_string) : 0));
- /* Flush any strings created in ErrorContext */
+ /* Flush strings created in ErrorContext (ereport might not have) */
FlushErrorState();
return false;
}
@@ -6883,7 +6883,7 @@ call_int_check_hook(struct config_int *conf, int *newval, void **extra,
errdetail_internal("%s", GUC_check_errdetail_string) : 0,
GUC_check_errhint_string ?
errhint("%s", GUC_check_errhint_string) : 0));
- /* Flush any strings created in ErrorContext */
+ /* Flush strings created in ErrorContext (ereport might not have) */
FlushErrorState();
return false;
}
@@ -6917,7 +6917,7 @@ call_real_check_hook(struct config_real *conf, double *newval, void **extra,
errdetail_internal("%s", GUC_check_errdetail_string) : 0,
GUC_check_errhint_string ?
errhint("%s", GUC_check_errhint_string) : 0));
- /* Flush any strings created in ErrorContext */
+ /* Flush strings created in ErrorContext (ereport might not have) */
FlushErrorState();
return false;
}
@@ -6960,7 +6960,7 @@ call_string_check_hook(struct config_string *conf, char **newval, void **extra,
errdetail_internal("%s", GUC_check_errdetail_string) : 0,
GUC_check_errhint_string ?
errhint("%s", GUC_check_errhint_string) : 0));
- /* Flush any strings created in ErrorContext */
+ /* Flush strings created in ErrorContext (ereport might not have) */
FlushErrorState();
result = false;
}
@@ -7002,7 +7002,7 @@ call_enum_check_hook(struct config_enum *conf, int *newval, void **extra,
errdetail_internal("%s", GUC_check_errdetail_string) : 0,
GUC_check_errhint_string ?
errhint("%s", GUC_check_errhint_string) : 0));
- /* Flush any strings created in ErrorContext */
+ /* Flush strings created in ErrorContext (ereport might not have) */
FlushErrorState();
return false;
}