postgres.git / summary / log / commit / refs

commit    89a3cdb32a9e1a6545abd43ef385e6bb91d66cb9
Author:   Thomas Munro <tmunro@postgresql.org>
Date:     Thu Oct 17 00:24:50 2019 +0000
First released in: 13.0, 9.5.20, 9.6.16, 10.11, 11.6, 12.1

    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, Tom Lane
    Discussion: https://postgr.es/m/15726-6d67e4fa14f027b3%40postgresql.org


src/backend/utils/misc/guc.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c index 4c993db475f..5f019e611a7 100644 --- a/src/backend/utils/misc/guc.c +++ b/src/backend/utils/misc/guc.c @@ -9348,6 +9348,21 @@ 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 **error_context_name_and_value = (char **) arg; + + if (error_context_name_and_value) + errcontext("while setting parameter \"%s\" to \"%s\"", + error_context_name_and_value[0], + error_context_name_and_value[1]); +} + /* * RestoreGUCState: * Reads the GUC state at the specified address and updates the GUCs with the @@ -9366,6 +9381,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++) @@ -9378,9 +9394,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 *error_context_name_and_value[2]; varname = read_gucstate(&srcptr, srcend); varvalue = read_gucstate(&srcptr, srcend); @@ -9393,6 +9416,9 @@ RestoreGUCState(void *gucstate) read_gucstate_binary(&srcptr, srcend, &varscontext, sizeof(varscontext)); + error_context_name_and_value[0] = varname; + error_context_name_and_value[1] = varvalue; + error_context_callback.arg = &error_context_name_and_value[0]; result = set_config_option(varname, varvalue, varscontext, varsource, GUC_ACTION_SET, true, ERROR, true); if (result <= 0) @@ -9401,7 +9427,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; } /* [parent: 583d86f92aab]