From f69054f9c7edf5ea3b4abb92172e5754c99e4eeb Mon Sep 17 00:00:00 2001 From: Thomas Munro Date: Wed, 3 Apr 2019 07:57:25 +1300 Subject: [PATCH] When restoring GUCs in parallel workers, show an error context. Otherwise it can be hard to see where an error is coming from, when the parallel worker sets all the GUCs that it received from the leader. Bug #15726. Back-patch to 9.5, where RestoreGUCState() appeared. Reported-by: Tiago Anastacio Reviewed-by: Daniel Gustafsson Discussion: https://postgr.es/m/15726-6d67e4fa14f027b3%40postgresql.org --- src/backend/utils/misc/guc.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c index f7f726b5ae..af9a4dd567 100644 --- a/src/backend/utils/misc/guc.c +++ b/src/backend/utils/misc/guc.c @@ -10220,6 +10220,20 @@ read_gucstate_binary(char **srcptr, char *srcend, void *dest, Size size) *srcptr += size; } +/* + * Callback used to add a context message when reporting errors that occur + * while trying to restore GUCs in parallel workers. + */ +static void +guc_restore_error_context_callback(void *arg) +{ + char **pair = (char **) arg; + + if (pair) + errcontext("while setting parameter \"%s\" to \"%s\" in a parallel worker process", + pair[0], pair[1]); +} + /* * RestoreGUCState: * Reads the GUC state at the specified address and updates the GUCs with the @@ -10238,6 +10252,7 @@ RestoreGUCState(void *gucstate) char *srcend; Size len; int i; + ErrorContextCallback error_context_callback; /* See comment at can_skip_gucvar(). */ for (i = 0; i < num_guc_variables; i++) @@ -10250,9 +10265,16 @@ RestoreGUCState(void *gucstate) srcptr += sizeof(len); srcend = srcptr + len; + /* If the GUC value check fails, we want errors to show useful context. */ + error_context_callback.callback = guc_restore_error_context_callback; + error_context_callback.previous = error_context_stack; + error_context_callback.arg = NULL; + error_context_stack = &error_context_callback; + while (srcptr < srcend) { int result; + char *pair[2]; varname = read_gucstate(&srcptr, srcend); varvalue = read_gucstate(&srcptr, srcend); @@ -10267,6 +10289,9 @@ RestoreGUCState(void *gucstate) read_gucstate_binary(&srcptr, srcend, &varscontext, sizeof(varscontext)); + pair[0] = varname; + pair[1] = varvalue; + error_context_callback.arg = &pair[0]; result = set_config_option(varname, varvalue, varscontext, varsource, GUC_ACTION_SET, true, ERROR, true); if (result <= 0) @@ -10275,7 +10300,10 @@ RestoreGUCState(void *gucstate) errmsg("parameter \"%s\" could not be set", varname))); if (varsourcefile[0]) set_config_sourcefile(varname, varsourcefile, varsourceline); + error_context_callback.arg = NULL; } + + error_context_stack = error_context_callback.previous; } /* -- 2.21.0