summaryrefslogtreecommitdiff
path: root/src/timezone
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2011-05-11 19:57:38 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2011-05-11 19:57:38 -0400
commite05b866447899211a0c2df31bf0671faac4fc3e5 (patch)
tree1aee90804395285469b52ff6b1713130a0db3dff /src/timezone
parent6fc6686b48bc569b05ce711d18cf964498b217f2 (diff)
downloadpostgresql-e05b866447899211a0c2df31bf0671faac4fc3e5.tar.gz
Split PGC_S_DEFAULT into two values, for true boot_val vs computed default.
Failure to distinguish these cases is the real cause behind the recent reports of Windows builds crashing on 'infinity'::timestamp, which was directly due to failure to establish a value of timezone_abbreviations in postmaster child processes. The postmaster had the desired value, but write_one_nondefault_variable() didn't transmit it to backends. To fix that, invent a new value PGC_S_DYNAMIC_DEFAULT, and be sure to use that or PGC_S_ENV_VAR (as appropriate) for "default" settings that are computed during initialization. (We need both because there's at least one variable that could receive a value from either source.) This commit also fixes ProcessConfigFile's failure to restore the correct default value for certain GUC variables if they are set in postgresql.conf and then removed/commented out of the file. We have to recompute and reinstall the value for any GUC variable that could have received a value from PGC_S_DYNAMIC_DEFAULT or PGC_S_ENV_VAR sources, and there were a number of oversights. (That whole thing is a crock that needs to be redesigned, but not today.) However, I intentionally didn't make it work "exactly right" for the cases of timezone and log_timezone. The exactly right behavior would involve running select_default_timezone, which we'd have to do independently in each postgres process, causing the whole database to become entirely unresponsive for as much as several seconds. That didn't seem like a good idea, especially since the variable's removal from postgresql.conf might be just an accidental edit. Instead the behavior is to adopt the previously active setting as if it were default. Note that this patch creates an ABI break for extensions that use any of the PGC_S_XXX constants; they'll need to be recompiled.
Diffstat (limited to 'src/timezone')
-rw-r--r--src/timezone/pgtz.c37
1 files changed, 27 insertions, 10 deletions
diff --git a/src/timezone/pgtz.c b/src/timezone/pgtz.c
index cb66f6380b..622cf94c5a 100644
--- a/src/timezone/pgtz.c
+++ b/src/timezone/pgtz.c
@@ -1438,6 +1438,10 @@ pg_timezone_pre_initialize(void)
* This is called after initial loading of postgresql.conf. If no TimeZone
* setting was found therein, we try to derive one from the environment.
* Likewise for log_timezone.
+ *
+ * Note: this is also called from ProcessConfigFile, to re-establish valid
+ * GUC settings if the GUCs have been reset to default following their
+ * removal from postgresql.conf.
*/
void
pg_timezone_initialize(void)
@@ -1463,21 +1467,34 @@ pg_timezone_initialize(void)
log_timezone = def_tz;
}
- /* Now, set the timezone GUC if it's not already set */
- if (GetConfigOption("timezone", false) == NULL)
- {
- /* Tell GUC about the value. Will redundantly call pg_tzset() */
+ /*
+ * Now, set the timezone and log_timezone GUCs if they're still default.
+ * (This will redundantly call pg_tzset().)
+ *
+ * We choose to label these values PGC_S_ENV_VAR, rather than
+ * PGC_S_DYNAMIC_DEFAULT which would be functionally equivalent, because
+ * they came either from getenv("TZ") or from libc behavior that's
+ * determined by process environment of some kind.
+ *
+ * Note: in the case where a setting has just been removed from
+ * postgresql.conf, this code will not do what you might expect, namely
+ * call select_default_timezone() and install that value as the setting.
+ * Rather, the previously active setting --- typically the one from
+ * postgresql.conf --- will be reinstalled, relabeled as PGC_S_ENV_VAR.
+ * If we did try to install the "correct" default value, the effect would
+ * be that each postmaster child would independently run an extremely
+ * expensive search of the timezone database, bringing the database to its
+ * knees for possibly multiple seconds. This is so unpleasant, and could
+ * so easily be triggered quite unintentionally, that it seems better to
+ * violate the principle of least astonishment.
+ */
+ if (GetConfigOptionResetString("timezone") == NULL)
SetConfigOption("timezone", pg_get_timezone_name(session_timezone),
PGC_POSTMASTER, PGC_S_ENV_VAR);
- }
- /* Likewise for log timezone */
- if (GetConfigOption("log_timezone", false) == NULL)
- {
- /* Tell GUC about the value. Will redundantly call pg_tzset() */
+ if (GetConfigOptionResetString("log_timezone") == NULL)
SetConfigOption("log_timezone", pg_get_timezone_name(log_timezone),
PGC_POSTMASTER, PGC_S_ENV_VAR);
- }
}