Commit 3c8c55dd authored by Thomas Munro's avatar Thomas Munro

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
parent 6bda2af0
......@@ -10209,6 +10209,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
......@@ -10227,6 +10242,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++)
......@@ -10239,9 +10255,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);
......@@ -10256,6 +10279,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)
......@@ -10264,7 +10290,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;
}
/*
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment