]> granicus.if.org Git - postgresql/commitdiff
Change ParseConfigFp() so that it doesn't process unused entry of each parameter.
authorFujii Masao <fujii@postgresql.org>
Wed, 6 Aug 2014 05:49:43 +0000 (14:49 +0900)
committerFujii Masao <fujii@postgresql.org>
Wed, 6 Aug 2014 05:49:43 +0000 (14:49 +0900)
When more than one setting entries of same parameter exist in the
configuration file, PostgreSQL uses only entry appearing last in
configuration file scan. Since the other entries are not used,
ParseConfigFp() doesn't need to process them, but previously it did
that. This problematic behavior caused the configuration file scan
to detect invalid settings of unused entries (e.g., existence of
multiple entries of PGC_POSTMASTER parameter) and log the messages
complaining about them.

This commit changes the configuration file scan so that it processes
only last entry of each parameter.

Note that when multiple entries of same parameter exist both in
postgresql.conf and postgresql.auto.conf, unused entries in
postgresql.conf are still processed only at postmaster startup.

The problem has existed since old version, but a user is more likely
to encounter it since 9.4 where ALTER SYSTEM command was introduced.
So back-patch to 9.4.

Amit Kapila, slightly modified by me. Per report from Christoph Berg.

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

index 7d301055dd379499736d7b3f2ba8304a8bb62984..e6e11090abdced9d9c767927081f4edc3d3a2a00 100644 (file)
@@ -562,7 +562,9 @@ ParseConfigFp(FILE *fp, const char *config_file, int depth, int elevel,
        {
                char       *opt_name = NULL;
                char       *opt_value = NULL;
-               ConfigVariable *item;
+               ConfigVariable *item,
+                                          *cur_item = NULL,
+                                          *prev_item = NULL;
 
                if (token == GUC_EOL)   /* empty or comment line */
                        continue;
@@ -645,13 +647,41 @@ ParseConfigFp(FILE *fp, const char *config_file, int depth, int elevel,
                }
                else
                {
-                       /* ordinary variable, append to list */
+                       /*
+                        * ordinary variable, append to list.  For multiple items of
+                        * same parameter, retain only which comes later.
+                        */
                        item = palloc(sizeof *item);
                        item->name = opt_name;
                        item->value = opt_value;
                        item->filename = pstrdup(config_file);
                        item->sourceline = ConfigFileLineno-1;
                        item->next = NULL;
+
+                       /* Remove the existing item of same parameter from the list */
+                       for (cur_item = *head_p; cur_item; prev_item = cur_item,
+                                        cur_item = cur_item->next)
+                       {
+                               if (strcmp(item->name, cur_item->name) == 0)
+                               {
+                                       if (prev_item == NULL)
+                                               *head_p = cur_item->next;
+                                       else
+                                       {
+                                               prev_item->next = cur_item->next;
+                                               /*
+                                                * On removing last item in list, we need to update tail
+                                                * to ensure that list will be maintianed.
+                                                */
+                                               if (prev_item->next == NULL)
+                                                       *tail_p = prev_item;
+                                       }
+
+                                       pfree(cur_item);
+                                       break;
+                               }
+                       }
+
                        if (*head_p == NULL)
                                *head_p = item;
                        else