Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 1b188ea

Browse files
committedSep 4, 2022
Preparatory refactoring for compiling guc-file.c standalone
Mostly this involves moving ProcessConfigFileInternal() to guc.c and fixing the shared API to match. Reviewed by Andres Freund Discussion: https://www.postgresql.org/message-id/20220810171935.7k5zgnjwqzalzmtm%40awork3.anarazel.de Discussion: https://www.postgresql.org/message-id/CAFBsxsF8Gc2StS3haXofshHCzqNMRXiSxvQEYGwnFsTmsdwNeg@mail.gmail.com
1 parent 73b9d05 commit 1b188ea

File tree

3 files changed

+364
-365
lines changed

3 files changed

+364
-365
lines changed
 

‎src/backend/utils/misc/guc-file.l‎

Lines changed: 1 addition & 359 deletions
Original file line numberDiff line numberDiff line change
@@ -49,12 +49,6 @@ static sigjmp_buf *GUC_flex_fatal_jmp;
4949

5050
static void FreeConfigVariable(ConfigVariable *item);
5151

52-
static void record_config_file_error(const char *errmsg,
53-
const char *config_file,
54-
int lineno,
55-
ConfigVariable **head_p,
56-
ConfigVariable **tail_p);
57-
5852
static int GUC_flex_fatal(const char *msg);
5953

6054
/* LCOV_EXCL_START */
@@ -160,358 +154,6 @@ ProcessConfigFile(GucContext context)
160154
MemoryContextDelete(config_cxt);
161155
}
162156

163-
/*
164-
* This function handles both actual config file (re)loads and execution of
165-
* show_all_file_settings() (i.e., the pg_file_settings view). In the latter
166-
* case we don't apply any of the settings, but we make all the usual validity
167-
* checks, and we return the ConfigVariable list so that it can be printed out
168-
* by show_all_file_settings().
169-
*/
170-
static ConfigVariable *
171-
ProcessConfigFileInternal(GucContext context, bool applySettings, int elevel)
172-
{
173-
bool error = false;
174-
bool applying = false;
175-
const char *ConfFileWithError;
176-
ConfigVariable *item,
177-
*head,
178-
*tail;
179-
int i;
180-
181-
/* Parse the main config file into a list of option names and values */
182-
ConfFileWithError = ConfigFileName;
183-
head = tail = NULL;
184-
185-
if (!ParseConfigFile(ConfigFileName, true,
186-
NULL, 0, 0, elevel,
187-
&head, &tail))
188-
{
189-
/* Syntax error(s) detected in the file, so bail out */
190-
error = true;
191-
goto bail_out;
192-
}
193-
194-
/*
195-
* Parse the PG_AUTOCONF_FILENAME file, if present, after the main file to
196-
* replace any parameters set by ALTER SYSTEM command. Because this file
197-
* is in the data directory, we can't read it until the DataDir has been
198-
* set.
199-
*/
200-
if (DataDir)
201-
{
202-
if (!ParseConfigFile(PG_AUTOCONF_FILENAME, false,
203-
NULL, 0, 0, elevel,
204-
&head, &tail))
205-
{
206-
/* Syntax error(s) detected in the file, so bail out */
207-
error = true;
208-
ConfFileWithError = PG_AUTOCONF_FILENAME;
209-
goto bail_out;
210-
}
211-
}
212-
else
213-
{
214-
/*
215-
* If DataDir is not set, the PG_AUTOCONF_FILENAME file cannot be
216-
* read. In this case, we don't want to accept any settings but
217-
* data_directory from postgresql.conf, because they might be
218-
* overwritten with settings in the PG_AUTOCONF_FILENAME file which
219-
* will be read later. OTOH, since data_directory isn't allowed in the
220-
* PG_AUTOCONF_FILENAME file, it will never be overwritten later.
221-
*/
222-
ConfigVariable *newlist = NULL;
223-
224-
/*
225-
* Prune all items except the last "data_directory" from the list.
226-
*/
227-
for (item = head; item; item = item->next)
228-
{
229-
if (!item->ignore &&
230-
strcmp(item->name, "data_directory") == 0)
231-
newlist = item;
232-
}
233-
234-
if (newlist)
235-
newlist->next = NULL;
236-
head = tail = newlist;
237-
238-
/*
239-
* Quick exit if data_directory is not present in file.
240-
*
241-
* We need not do any further processing, in particular we don't set
242-
* PgReloadTime; that will be set soon by subsequent full loading of
243-
* the config file.
244-
*/
245-
if (head == NULL)
246-
goto bail_out;
247-
}
248-
249-
/*
250-
* Mark all extant GUC variables as not present in the config file. We
251-
* need this so that we can tell below which ones have been removed from
252-
* the file since we last processed it.
253-
*/
254-
for (i = 0; i < num_guc_variables; i++)
255-
{
256-
struct config_generic *gconf = guc_variables[i];
257-
258-
gconf->status &= ~GUC_IS_IN_FILE;
259-
}
260-
261-
/*
262-
* Check if all the supplied option names are valid, as an additional
263-
* quasi-syntactic check on the validity of the config file. It is
264-
* important that the postmaster and all backends agree on the results of
265-
* this phase, else we will have strange inconsistencies about which
266-
* processes accept a config file update and which don't. Hence, unknown
267-
* custom variable names have to be accepted without complaint. For the
268-
* same reason, we don't attempt to validate the options' values here.
269-
*
270-
* In addition, the GUC_IS_IN_FILE flag is set on each existing GUC
271-
* variable mentioned in the file; and we detect duplicate entries in the
272-
* file and mark the earlier occurrences as ignorable.
273-
*/
274-
for (item = head; item; item = item->next)
275-
{
276-
struct config_generic *record;
277-
278-
/* Ignore anything already marked as ignorable */
279-
if (item->ignore)
280-
continue;
281-
282-
/*
283-
* Try to find the variable; but do not create a custom placeholder if
284-
* it's not there already.
285-
*/
286-
record = find_option(item->name, false, true, elevel);
287-
288-
if (record)
289-
{
290-
/* If it's already marked, then this is a duplicate entry */
291-
if (record->status & GUC_IS_IN_FILE)
292-
{
293-
/*
294-
* Mark the earlier occurrence(s) as dead/ignorable. We could
295-
* avoid the O(N^2) behavior here with some additional state,
296-
* but it seems unlikely to be worth the trouble.
297-
*/
298-
ConfigVariable *pitem;
299-
300-
for (pitem = head; pitem != item; pitem = pitem->next)
301-
{
302-
if (!pitem->ignore &&
303-
strcmp(pitem->name, item->name) == 0)
304-
pitem->ignore = true;
305-
}
306-
}
307-
/* Now mark it as present in file */
308-
record->status |= GUC_IS_IN_FILE;
309-
}
310-
else if (!valid_custom_variable_name(item->name))
311-
{
312-
/* Invalid non-custom variable, so complain */
313-
ereport(elevel,
314-
(errcode(ERRCODE_UNDEFINED_OBJECT),
315-
errmsg("unrecognized configuration parameter \"%s\" in file \"%s\" line %d",
316-
item->name,
317-
item->filename, item->sourceline)));
318-
item->errmsg = pstrdup("unrecognized configuration parameter");
319-
error = true;
320-
ConfFileWithError = item->filename;
321-
}
322-
}
323-
324-
/*
325-
* If we've detected any errors so far, we don't want to risk applying any
326-
* changes.
327-
*/
328-
if (error)
329-
goto bail_out;
330-
331-
/* Otherwise, set flag that we're beginning to apply changes */
332-
applying = true;
333-
334-
/*
335-
* Check for variables having been removed from the config file, and
336-
* revert their reset values (and perhaps also effective values) to the
337-
* boot-time defaults. If such a variable can't be changed after startup,
338-
* report that and continue.
339-
*/
340-
for (i = 0; i < num_guc_variables; i++)
341-
{
342-
struct config_generic *gconf = guc_variables[i];
343-
GucStack *stack;
344-
345-
if (gconf->reset_source != PGC_S_FILE ||
346-
(gconf->status & GUC_IS_IN_FILE))
347-
continue;
348-
if (gconf->context < PGC_SIGHUP)
349-
{
350-
/* The removal can't be effective without a restart */
351-
gconf->status |= GUC_PENDING_RESTART;
352-
ereport(elevel,
353-
(errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM),
354-
errmsg("parameter \"%s\" cannot be changed without restarting the server",
355-
gconf->name)));
356-
record_config_file_error(psprintf("parameter \"%s\" cannot be changed without restarting the server",
357-
gconf->name),
358-
NULL, 0,
359-
&head, &tail);
360-
error = true;
361-
continue;
362-
}
363-
364-
/* No more to do if we're just doing show_all_file_settings() */
365-
if (!applySettings)
366-
continue;
367-
368-
/*
369-
* Reset any "file" sources to "default", else set_config_option will
370-
* not override those settings.
371-
*/
372-
if (gconf->reset_source == PGC_S_FILE)
373-
gconf->reset_source = PGC_S_DEFAULT;
374-
if (gconf->source == PGC_S_FILE)
375-
gconf->source = PGC_S_DEFAULT;
376-
for (stack = gconf->stack; stack; stack = stack->prev)
377-
{
378-
if (stack->source == PGC_S_FILE)
379-
stack->source = PGC_S_DEFAULT;
380-
}
381-
382-
/* Now we can re-apply the wired-in default (i.e., the boot_val) */
383-
if (set_config_option(gconf->name, NULL,
384-
context, PGC_S_DEFAULT,
385-
GUC_ACTION_SET, true, 0, false) > 0)
386-
{
387-
/* Log the change if appropriate */
388-
if (context == PGC_SIGHUP)
389-
ereport(elevel,
390-
(errmsg("parameter \"%s\" removed from configuration file, reset to default",
391-
gconf->name)));
392-
}
393-
}
394-
395-
/*
396-
* Restore any variables determined by environment variables or
397-
* dynamically-computed defaults. This is a no-op except in the case
398-
* where one of these had been in the config file and is now removed.
399-
*
400-
* In particular, we *must not* do this during the postmaster's initial
401-
* loading of the file, since the timezone functions in particular should
402-
* be run only after initialization is complete.
403-
*
404-
* XXX this is an unmaintainable crock, because we have to know how to set
405-
* (or at least what to call to set) every non-PGC_INTERNAL variable that
406-
* could potentially have PGC_S_DYNAMIC_DEFAULT or PGC_S_ENV_VAR source.
407-
*/
408-
if (context == PGC_SIGHUP && applySettings)
409-
{
410-
InitializeGUCOptionsFromEnvironment();
411-
pg_timezone_abbrev_initialize();
412-
/* this selects SQL_ASCII in processes not connected to a database */
413-
SetConfigOption("client_encoding", GetDatabaseEncodingName(),
414-
PGC_BACKEND, PGC_S_DYNAMIC_DEFAULT);
415-
}
416-
417-
/*
418-
* Now apply the values from the config file.
419-
*/
420-
for (item = head; item; item = item->next)
421-
{
422-
char *pre_value = NULL;
423-
int scres;
424-
425-
/* Ignore anything marked as ignorable */
426-
if (item->ignore)
427-
continue;
428-
429-
/* In SIGHUP cases in the postmaster, we want to report changes */
430-
if (context == PGC_SIGHUP && applySettings && !IsUnderPostmaster)
431-
{
432-
const char *preval = GetConfigOption(item->name, true, false);
433-
434-
/* If option doesn't exist yet or is NULL, treat as empty string */
435-
if (!preval)
436-
preval = "";
437-
/* must dup, else might have dangling pointer below */
438-
pre_value = pstrdup(preval);
439-
}
440-
441-
scres = set_config_option(item->name, item->value,
442-
context, PGC_S_FILE,
443-
GUC_ACTION_SET, applySettings, 0, false);
444-
if (scres > 0)
445-
{
446-
/* variable was updated, so log the change if appropriate */
447-
if (pre_value)
448-
{
449-
const char *post_value = GetConfigOption(item->name, true, false);
450-
451-
if (!post_value)
452-
post_value = "";
453-
if (strcmp(pre_value, post_value) != 0)
454-
ereport(elevel,
455-
(errmsg("parameter \"%s\" changed to \"%s\"",
456-
item->name, item->value)));
457-
}
458-
item->applied = true;
459-
}
460-
else if (scres == 0)
461-
{
462-
error = true;
463-
item->errmsg = pstrdup("setting could not be applied");
464-
ConfFileWithError = item->filename;
465-
}
466-
else
467-
{
468-
/* no error, but variable's active value was not changed */
469-
item->applied = true;
470-
}
471-
472-
/*
473-
* We should update source location unless there was an error, since
474-
* even if the active value didn't change, the reset value might have.
475-
* (In the postmaster, there won't be a difference, but it does matter
476-
* in backends.)
477-
*/
478-
if (scres != 0 && applySettings)
479-
set_config_sourcefile(item->name, item->filename,
480-
item->sourceline);
481-
482-
if (pre_value)
483-
pfree(pre_value);
484-
}
485-
486-
/* Remember when we last successfully loaded the config file. */
487-
if (applySettings)
488-
PgReloadTime = GetCurrentTimestamp();
489-
490-
bail_out:
491-
if (error && applySettings)
492-
{
493-
/* During postmaster startup, any error is fatal */
494-
if (context == PGC_POSTMASTER)
495-
ereport(ERROR,
496-
(errcode(ERRCODE_CONFIG_FILE_ERROR),
497-
errmsg("configuration file \"%s\" contains errors",
498-
ConfFileWithError)));
499-
else if (applying)
500-
ereport(elevel,
501-
(errcode(ERRCODE_CONFIG_FILE_ERROR),
502-
errmsg("configuration file \"%s\" contains errors; unaffected changes were applied",
503-
ConfFileWithError)));
504-
else
505-
ereport(elevel,
506-
(errcode(ERRCODE_CONFIG_FILE_ERROR),
507-
errmsg("configuration file \"%s\" contains errors; no changes were applied",
508-
ConfFileWithError)));
509-
}
510-
511-
/* Successful or otherwise, return the collected data list */
512-
return head;
513-
}
514-
515157
/*
516158
* Given a configuration file or directory location that may be a relative
517159
* path, return an absolute one. We consider the location to be relative to
@@ -660,7 +302,7 @@ cleanup:
660302
* Capture an error message in the ConfigVariable list returned by
661303
* config file parsing.
662304
*/
663-
static void
305+
void
664306
record_config_file_error(const char *errmsg,
665307
const char *config_file,
666308
int lineno,

‎src/backend/utils/misc/guc.c‎

Lines changed: 354 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -243,10 +243,6 @@ static void assign_recovery_target_lsn(const char *newval, void *extra);
243243
static bool check_primary_slot_name(char **newval, void **extra, GucSource source);
244244
static bool check_default_with_oids(bool *newval, void **extra, GucSource source);
245245

246-
/* Private functions in guc-file.l that need to be called from guc.c */
247-
static ConfigVariable *ProcessConfigFileInternal(GucContext context,
248-
bool applySettings, int elevel);
249-
250246
/*
251247
* Track whether there were any deferred checks for custom resource managers
252248
* specified in wal_consistency_checking.
@@ -5160,8 +5156,8 @@ static bool report_needed; /* true if any GUC_REPORT reports are needed */
51605156
static int GUCNestLevel = 0; /* 1 when in main transaction */
51615157

51625158

5159+
static struct config_generic *find_option(const char *name, bool create_placeholders, bool skip_errors, int elevel);
51635160
static int guc_var_compare(const void *a, const void *b);
5164-
static int guc_name_compare(const char *namea, const char *nameb);
51655161
static void InitializeGUCOptionsFromEnvironment(void);
51665162
static void InitializeOneGUCOption(struct config_generic *gconf);
51675163
static void push_old_value(struct config_generic *gconf, GucAction action);
@@ -5180,7 +5176,359 @@ static bool validate_option_array_item(const char *name, const char *value,
51805176
static void write_auto_conf_file(int fd, const char *filename, ConfigVariable *head_p);
51815177
static void replace_auto_config_value(ConfigVariable **head_p, ConfigVariable **tail_p,
51825178
const char *name, const char *value);
5179+
static bool valid_custom_variable_name(const char *name);
5180+
5181+
/*
5182+
* This function handles both actual config file (re)loads and execution of
5183+
* show_all_file_settings() (i.e., the pg_file_settings view). In the latter
5184+
* case we don't apply any of the settings, but we make all the usual validity
5185+
* checks, and we return the ConfigVariable list so that it can be printed out
5186+
* by show_all_file_settings().
5187+
*/
5188+
ConfigVariable *
5189+
ProcessConfigFileInternal(GucContext context, bool applySettings, int elevel)
5190+
{
5191+
bool error = false;
5192+
bool applying = false;
5193+
const char *ConfFileWithError;
5194+
ConfigVariable *item,
5195+
*head,
5196+
*tail;
5197+
int i;
5198+
5199+
/* Parse the main config file into a list of option names and values */
5200+
ConfFileWithError = ConfigFileName;
5201+
head = tail = NULL;
5202+
5203+
if (!ParseConfigFile(ConfigFileName, true,
5204+
NULL, 0, 0, elevel,
5205+
&head, &tail))
5206+
{
5207+
/* Syntax error(s) detected in the file, so bail out */
5208+
error = true;
5209+
goto bail_out;
5210+
}
5211+
5212+
/*
5213+
* Parse the PG_AUTOCONF_FILENAME file, if present, after the main file to
5214+
* replace any parameters set by ALTER SYSTEM command. Because this file
5215+
* is in the data directory, we can't read it until the DataDir has been
5216+
* set.
5217+
*/
5218+
if (DataDir)
5219+
{
5220+
if (!ParseConfigFile(PG_AUTOCONF_FILENAME, false,
5221+
NULL, 0, 0, elevel,
5222+
&head, &tail))
5223+
{
5224+
/* Syntax error(s) detected in the file, so bail out */
5225+
error = true;
5226+
ConfFileWithError = PG_AUTOCONF_FILENAME;
5227+
goto bail_out;
5228+
}
5229+
}
5230+
else
5231+
{
5232+
/*
5233+
* If DataDir is not set, the PG_AUTOCONF_FILENAME file cannot be
5234+
* read. In this case, we don't want to accept any settings but
5235+
* data_directory from postgresql.conf, because they might be
5236+
* overwritten with settings in the PG_AUTOCONF_FILENAME file which
5237+
* will be read later. OTOH, since data_directory isn't allowed in the
5238+
* PG_AUTOCONF_FILENAME file, it will never be overwritten later.
5239+
*/
5240+
ConfigVariable *newlist = NULL;
5241+
5242+
/*
5243+
* Prune all items except the last "data_directory" from the list.
5244+
*/
5245+
for (item = head; item; item = item->next)
5246+
{
5247+
if (!item->ignore &&
5248+
strcmp(item->name, "data_directory") == 0)
5249+
newlist = item;
5250+
}
51835251

5252+
if (newlist)
5253+
newlist->next = NULL;
5254+
head = tail = newlist;
5255+
5256+
/*
5257+
* Quick exit if data_directory is not present in file.
5258+
*
5259+
* We need not do any further processing, in particular we don't set
5260+
* PgReloadTime; that will be set soon by subsequent full loading of
5261+
* the config file.
5262+
*/
5263+
if (head == NULL)
5264+
goto bail_out;
5265+
}
5266+
5267+
/*
5268+
* Mark all extant GUC variables as not present in the config file. We
5269+
* need this so that we can tell below which ones have been removed from
5270+
* the file since we last processed it.
5271+
*/
5272+
for (i = 0; i < num_guc_variables; i++)
5273+
{
5274+
struct config_generic *gconf = guc_variables[i];
5275+
5276+
gconf->status &= ~GUC_IS_IN_FILE;
5277+
}
5278+
5279+
/*
5280+
* Check if all the supplied option names are valid, as an additional
5281+
* quasi-syntactic check on the validity of the config file. It is
5282+
* important that the postmaster and all backends agree on the results of
5283+
* this phase, else we will have strange inconsistencies about which
5284+
* processes accept a config file update and which don't. Hence, unknown
5285+
* custom variable names have to be accepted without complaint. For the
5286+
* same reason, we don't attempt to validate the options' values here.
5287+
*
5288+
* In addition, the GUC_IS_IN_FILE flag is set on each existing GUC
5289+
* variable mentioned in the file; and we detect duplicate entries in the
5290+
* file and mark the earlier occurrences as ignorable.
5291+
*/
5292+
for (item = head; item; item = item->next)
5293+
{
5294+
struct config_generic *record;
5295+
5296+
/* Ignore anything already marked as ignorable */
5297+
if (item->ignore)
5298+
continue;
5299+
5300+
/*
5301+
* Try to find the variable; but do not create a custom placeholder if
5302+
* it's not there already.
5303+
*/
5304+
record = find_option(item->name, false, true, elevel);
5305+
5306+
if (record)
5307+
{
5308+
/* If it's already marked, then this is a duplicate entry */
5309+
if (record->status & GUC_IS_IN_FILE)
5310+
{
5311+
/*
5312+
* Mark the earlier occurrence(s) as dead/ignorable. We could
5313+
* avoid the O(N^2) behavior here with some additional state,
5314+
* but it seems unlikely to be worth the trouble.
5315+
*/
5316+
ConfigVariable *pitem;
5317+
5318+
for (pitem = head; pitem != item; pitem = pitem->next)
5319+
{
5320+
if (!pitem->ignore &&
5321+
strcmp(pitem->name, item->name) == 0)
5322+
pitem->ignore = true;
5323+
}
5324+
}
5325+
/* Now mark it as present in file */
5326+
record->status |= GUC_IS_IN_FILE;
5327+
}
5328+
else if (!valid_custom_variable_name(item->name))
5329+
{
5330+
/* Invalid non-custom variable, so complain */
5331+
ereport(elevel,
5332+
(errcode(ERRCODE_UNDEFINED_OBJECT),
5333+
errmsg("unrecognized configuration parameter \"%s\" in file \"%s\" line %d",
5334+
item->name,
5335+
item->filename, item->sourceline)));
5336+
item->errmsg = pstrdup("unrecognized configuration parameter");
5337+
error = true;
5338+
ConfFileWithError = item->filename;
5339+
}
5340+
}
5341+
5342+
/*
5343+
* If we've detected any errors so far, we don't want to risk applying any
5344+
* changes.
5345+
*/
5346+
if (error)
5347+
goto bail_out;
5348+
5349+
/* Otherwise, set flag that we're beginning to apply changes */
5350+
applying = true;
5351+
5352+
/*
5353+
* Check for variables having been removed from the config file, and
5354+
* revert their reset values (and perhaps also effective values) to the
5355+
* boot-time defaults. If such a variable can't be changed after startup,
5356+
* report that and continue.
5357+
*/
5358+
for (i = 0; i < num_guc_variables; i++)
5359+
{
5360+
struct config_generic *gconf = guc_variables[i];
5361+
GucStack *stack;
5362+
5363+
if (gconf->reset_source != PGC_S_FILE ||
5364+
(gconf->status & GUC_IS_IN_FILE))
5365+
continue;
5366+
if (gconf->context < PGC_SIGHUP)
5367+
{
5368+
/* The removal can't be effective without a restart */
5369+
gconf->status |= GUC_PENDING_RESTART;
5370+
ereport(elevel,
5371+
(errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM),
5372+
errmsg("parameter \"%s\" cannot be changed without restarting the server",
5373+
gconf->name)));
5374+
record_config_file_error(psprintf("parameter \"%s\" cannot be changed without restarting the server",
5375+
gconf->name),
5376+
NULL, 0,
5377+
&head, &tail);
5378+
error = true;
5379+
continue;
5380+
}
5381+
5382+
/* No more to do if we're just doing show_all_file_settings() */
5383+
if (!applySettings)
5384+
continue;
5385+
5386+
/*
5387+
* Reset any "file" sources to "default", else set_config_option will
5388+
* not override those settings.
5389+
*/
5390+
if (gconf->reset_source == PGC_S_FILE)
5391+
gconf->reset_source = PGC_S_DEFAULT;
5392+
if (gconf->source == PGC_S_FILE)
5393+
gconf->source = PGC_S_DEFAULT;
5394+
for (stack = gconf->stack; stack; stack = stack->prev)
5395+
{
5396+
if (stack->source == PGC_S_FILE)
5397+
stack->source = PGC_S_DEFAULT;
5398+
}
5399+
5400+
/* Now we can re-apply the wired-in default (i.e., the boot_val) */
5401+
if (set_config_option(gconf->name, NULL,
5402+
context, PGC_S_DEFAULT,
5403+
GUC_ACTION_SET, true, 0, false) > 0)
5404+
{
5405+
/* Log the change if appropriate */
5406+
if (context == PGC_SIGHUP)
5407+
ereport(elevel,
5408+
(errmsg("parameter \"%s\" removed from configuration file, reset to default",
5409+
gconf->name)));
5410+
}
5411+
}
5412+
5413+
/*
5414+
* Restore any variables determined by environment variables or
5415+
* dynamically-computed defaults. This is a no-op except in the case
5416+
* where one of these had been in the config file and is now removed.
5417+
*
5418+
* In particular, we *must not* do this during the postmaster's initial
5419+
* loading of the file, since the timezone functions in particular should
5420+
* be run only after initialization is complete.
5421+
*
5422+
* XXX this is an unmaintainable crock, because we have to know how to set
5423+
* (or at least what to call to set) every non-PGC_INTERNAL variable that
5424+
* could potentially have PGC_S_DYNAMIC_DEFAULT or PGC_S_ENV_VAR source.
5425+
*/
5426+
if (context == PGC_SIGHUP && applySettings)
5427+
{
5428+
InitializeGUCOptionsFromEnvironment();
5429+
pg_timezone_abbrev_initialize();
5430+
/* this selects SQL_ASCII in processes not connected to a database */
5431+
SetConfigOption("client_encoding", GetDatabaseEncodingName(),
5432+
PGC_BACKEND, PGC_S_DYNAMIC_DEFAULT);
5433+
}
5434+
5435+
/*
5436+
* Now apply the values from the config file.
5437+
*/
5438+
for (item = head; item; item = item->next)
5439+
{
5440+
char *pre_value = NULL;
5441+
int scres;
5442+
5443+
/* Ignore anything marked as ignorable */
5444+
if (item->ignore)
5445+
continue;
5446+
5447+
/* In SIGHUP cases in the postmaster, we want to report changes */
5448+
if (context == PGC_SIGHUP && applySettings && !IsUnderPostmaster)
5449+
{
5450+
const char *preval = GetConfigOption(item->name, true, false);
5451+
5452+
/* If option doesn't exist yet or is NULL, treat as empty string */
5453+
if (!preval)
5454+
preval = "";
5455+
/* must dup, else might have dangling pointer below */
5456+
pre_value = pstrdup(preval);
5457+
}
5458+
5459+
scres = set_config_option(item->name, item->value,
5460+
context, PGC_S_FILE,
5461+
GUC_ACTION_SET, applySettings, 0, false);
5462+
if (scres > 0)
5463+
{
5464+
/* variable was updated, so log the change if appropriate */
5465+
if (pre_value)
5466+
{
5467+
const char *post_value = GetConfigOption(item->name, true, false);
5468+
5469+
if (!post_value)
5470+
post_value = "";
5471+
if (strcmp(pre_value, post_value) != 0)
5472+
ereport(elevel,
5473+
(errmsg("parameter \"%s\" changed to \"%s\"",
5474+
item->name, item->value)));
5475+
}
5476+
item->applied = true;
5477+
}
5478+
else if (scres == 0)
5479+
{
5480+
error = true;
5481+
item->errmsg = pstrdup("setting could not be applied");
5482+
ConfFileWithError = item->filename;
5483+
}
5484+
else
5485+
{
5486+
/* no error, but variable's active value was not changed */
5487+
item->applied = true;
5488+
}
5489+
5490+
/*
5491+
* We should update source location unless there was an error, since
5492+
* even if the active value didn't change, the reset value might have.
5493+
* (In the postmaster, there won't be a difference, but it does matter
5494+
* in backends.)
5495+
*/
5496+
if (scres != 0 && applySettings)
5497+
set_config_sourcefile(item->name, item->filename,
5498+
item->sourceline);
5499+
5500+
if (pre_value)
5501+
pfree(pre_value);
5502+
}
5503+
5504+
/* Remember when we last successfully loaded the config file. */
5505+
if (applySettings)
5506+
PgReloadTime = GetCurrentTimestamp();
5507+
5508+
bail_out:
5509+
if (error && applySettings)
5510+
{
5511+
/* During postmaster startup, any error is fatal */
5512+
if (context == PGC_POSTMASTER)
5513+
ereport(ERROR,
5514+
(errcode(ERRCODE_CONFIG_FILE_ERROR),
5515+
errmsg("configuration file \"%s\" contains errors",
5516+
ConfFileWithError)));
5517+
else if (applying)
5518+
ereport(elevel,
5519+
(errcode(ERRCODE_CONFIG_FILE_ERROR),
5520+
errmsg("configuration file \"%s\" contains errors; unaffected changes were applied",
5521+
ConfFileWithError)));
5522+
else
5523+
ereport(elevel,
5524+
(errcode(ERRCODE_CONFIG_FILE_ERROR),
5525+
errmsg("configuration file \"%s\" contains errors; no changes were applied",
5526+
ConfFileWithError)));
5527+
}
5528+
5529+
/* Successful or otherwise, return the collected data list */
5530+
return head;
5531+
}
51845532

51855533
/*
51865534
* Some infrastructure for checking malloc/strdup/realloc calls
@@ -5737,7 +6085,7 @@ guc_var_compare(const void *a, const void *b)
57376085
/*
57386086
* the bare comparison function for GUC names
57396087
*/
5740-
static int
6088+
int
57416089
guc_name_compare(const char *namea, const char *nameb)
57426090
{
57436091
/*

‎src/include/utils/guc.h‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -442,6 +442,15 @@ extern void GUC_check_errcode(int sqlerrcode);
442442
pre_format_elog_string(errno, TEXTDOMAIN), \
443443
GUC_check_errhint_string = format_elog_string
444444

445+
/* functions shared between guc.c and guc-file.l */
446+
extern int guc_name_compare(const char *namea, const char *nameb);
447+
extern ConfigVariable *ProcessConfigFileInternal(GucContext context,
448+
bool applySettings, int elevel);
449+
extern void record_config_file_error(const char *errmsg,
450+
const char *config_file,
451+
int lineno,
452+
ConfigVariable **head_p,
453+
ConfigVariable **tail_p);
445454

446455
/*
447456
* The following functions are not in guc.c, but are declared here to avoid

0 commit comments

Comments
 (0)
Please sign in to comment.