diff options
-rw-r--r-- | src/backend/utils/error/elog.c | 17 | ||||
-rw-r--r-- | src/backend/utils/misc/guc.c | 10 |
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; } |