Fix a couple of issues in recent patch to print updates to postgresql.conf
authorTom Lane <[email protected]>
Sat, 3 Oct 2009 18:04:57 +0000 (18:04 +0000)
committerTom Lane <[email protected]>
Sat, 3 Oct 2009 18:04:57 +0000 (18:04 +0000)
settings: avoid calling superuser() in contexts where it's not defined,
don't leak the transient copies of GetConfigOption output, and avoid the
whole exercise in postmaster child processes.

I found that actually no current caller of GetConfigOption has any use for
its internal check of GUC_SUPERUSER_ONLY.  But rather than just remove
that entirely, it seemed better to add a parameter indicating whether to
enforce the check.

Per report from Simon and subsequent testing.

src/backend/utils/misc/guc-file.l
src/backend/utils/misc/guc.c
src/include/utils/guc.h
src/timezone/pgtz.c

index 57c86868235dea82df56d362d6187c1d15700bc4..3170096b192bce6d352767f15d6bffd275aba07e 100644 (file)
@@ -312,21 +312,26 @@ ProcessConfigFile(GucContext context)
        /* If we got here all the options checked out okay, so apply them. */
        for (item = head; item; item = item->next)
        {
-               char *pre_value = NULL;
+               char   *pre_value = NULL;
 
-               if (context == PGC_SIGHUP)
-                       pre_value = pstrdup(GetConfigOption(item->name));
+               /* In SIGHUP cases in the postmaster, report changes */
+               if (context == PGC_SIGHUP && !IsUnderPostmaster)
+                       pre_value = pstrdup(GetConfigOption(item->name, false));
 
                if (set_config_option(item->name, item->value, context,
                                                                 PGC_S_FILE, GUC_ACTION_SET, true))
                {
-                       if (pre_value && strcmp(pre_value, GetConfigOption(item->name)) != 0)
+                       set_config_sourcefile(item->name, item->filename,
+                                                                 item->sourceline);
+                       if (pre_value &&
+                               strcmp(pre_value, GetConfigOption(item->name, false)) != 0)
                                ereport(elevel,
                                                (errmsg("parameter \"%s\" changed to \"%s\"",
                                                                item->name, item->value)));
-                       set_config_sourcefile(item->name, item->filename,
-                                                                 item->sourceline);
                }
+
+               if (pre_value)
+                       pfree(pre_value);
        }
 
        /* Remember when we last successfully loaded the config file. */
index fc55e9017ac1915df5727255b4b81e1898c5c48e..1f63e06962a30bcd149ef813602e5d1aa3ee92c2 100644 (file)
@@ -5197,11 +5197,15 @@ SetConfigOption(const char *name, const char *value,
  * Fetch the current value of the option `name'. If the option doesn't exist,
  * throw an ereport and don't return.
  *
+ * If restrict_superuser is true, we also enforce that only superusers can
+ * see GUC_SUPERUSER_ONLY variables.  This should only be passed as true
+ * in user-driven calls.
+ *
  * The string is *not* allocated for modification and is really only
  * valid until the next call to configuration related functions.
  */
 const char *
-GetConfigOption(const char *name)
+GetConfigOption(const char *name, bool restrict_superuser)
 {
        struct config_generic *record;
        static char buffer[256];
@@ -5211,7 +5215,9 @@ GetConfigOption(const char *name)
                ereport(ERROR,
                                (errcode(ERRCODE_UNDEFINED_OBJECT),
                           errmsg("unrecognized configuration parameter \"%s\"", name)));
-       if ((record->flags & GUC_SUPERUSER_ONLY) && !superuser())
+       if (restrict_superuser &&
+               (record->flags & GUC_SUPERUSER_ONLY) &&
+               !superuser())
                ereport(ERROR,
                                (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
                                 errmsg("must be superuser to examine \"%s\"", name)));
index 7abe41ac73eb198296f11794ca9bf628510f4b01..17a0985ad646d572141a613bdc9da9c19928c132 100644 (file)
@@ -249,7 +249,7 @@ extern void DefineCustomEnumVariable(
 
 extern void EmitWarningsOnPlaceholders(const char *className);
 
-extern const char *GetConfigOption(const char *name);
+extern const char *GetConfigOption(const char *name, bool restrict_superuser);
 extern const char *GetConfigOptionResetString(const char *name);
 extern void ProcessConfigFile(GucContext context);
 extern void InitializeGUCOptions(void);
index b14f2d631afe719da03789b982e7b0244c26a52b..32ccc9ae97f0268f1a1fabbf5956fb12bbae5f89 100644 (file)
@@ -1366,7 +1366,7 @@ pg_timezone_initialize(void)
        pg_tz      *def_tz = NULL;
 
        /* Do we need to try to figure the session timezone? */
-       if (pg_strcasecmp(GetConfigOption("timezone"), "UNKNOWN") == 0)
+       if (pg_strcasecmp(GetConfigOption("timezone", false), "UNKNOWN") == 0)
        {
                /* Select setting */
                def_tz = select_default_timezone();
@@ -1377,7 +1377,7 @@ pg_timezone_initialize(void)
        }
 
        /* What about the log timezone? */
-       if (pg_strcasecmp(GetConfigOption("log_timezone"), "UNKNOWN") == 0)
+       if (pg_strcasecmp(GetConfigOption("log_timezone", false), "UNKNOWN") == 0)
        {
                /* Select setting, but don't duplicate work */
                if (!def_tz)