PGC_S_DEFAULT is inadequate - Mailing list pgsql-hackers
From | Tom Lane |
---|---|
Subject | PGC_S_DEFAULT is inadequate |
Date | |
Msg-id | 17311.1305080416@sss.pgh.pa.us Whole thread Raw |
Responses |
Re: PGC_S_DEFAULT is inadequate
Re: PGC_S_DEFAULT is inadequate |
List | pgsql-hackers |
I believe I've sussed the reason for the recent reports of Windows builds crashing when asked to process 'infinity'::timestamp. It's a bit tedious, so bear with me: 1. The immediate cause is that datebsearch() is being called with a NULL pointer and zero count, ie, the powerup default values of timezonetktbl and sztimezonetktbl, because InstallTimeZoneAbbrevs is never called, because the GUC variable timezone_abbreviations is never set. That routine should be a bit more robust about the case, and I've already fixed that, but the underlying failure to initialize the GUC variable remains a problem. 2. The 9.1 change that created the issue is that I changed pg_timezone_abbrev_initialize to use a source value of PGC_S_DEFAULT instead of the previous, rather arbitrary choice of PGC_S_ARGV. That seemed like a good idea at the time because (a) it looked a lot saner in pg_settings and (b) it wouldn't override a setting coming from the postmaster's command line, should anyone ever try to do that (evidently no one ever has, or at least not complained to us that it didn't work). 3. The reason it fails in Windows and nowhere else is that write_one_nondefault_variable() ignores and doesn't write out variables having source == PGC_S_DEFAULT. So, even though the postmaster has correctly set its own value of timezone_abbreviations, child processes don't receive that setting. You can duplicate this behavior in a non-Windows machine if you #define EXEC_BACKEND. Too bad it didn't occur to me to test the GUC assign hook changes that way. Although I might not have found it anyway, because: 4. The problem is masked in the regression database because we create a database-level setting of timezone_abbreviations, so that backends do receive a value of the GUC before they are ever asked to parse any timestamp values. Else we would have seen this immediately in the buildfarm. Isn't that special? Effectively, write_one_nondefault_variable is assuming that variables having source == PGC_S_DEFAULT *must* have exactly their boot values. It turns out there's another place making the same assumption, namely the kludge in guc-file.l that tries to reset variables that were formerly set by postgresql.conf and no longer are. What it does is to reset them using source == PGC_S_DEFAULT, which will override the existing setting with the boot_val if and only if the variable currently has source == PGC_S_DEFAULT, which it just forced to be the case for anything previously having source == PGC_S_FILE. So this is fine if the current value was from the file or was the boot_val, but if we'd overridden the boot value with a "replacement" default value using PGC_S_DEFAULT, that code would cause the value to revert to the boot_val not the replacement value. Not desirable. So, having recognized these two problems, I was about to knuckle under and make the "replacement default" value in pg_timezone_abbrev_initialize be assigned with source PGC_S_ENV_VAR, which is the next step up. That would be ugly in the sense of exposing a confusing source value in pg_settings, but it would not have any worse effects because there is no real environment variable from which we might absorb a setting for timezone_abbreviations. But wait: there's another place that's also using PGC_S_DEFAULT like this, and that's the assignment of client_encoding from database encoding in postinit.c. And for that variable, there *is* a potential assignment from an environment variable, namely we will absorb a value from PGCLIENTENCODING if that's set in the server environment. (For the record, I take no position on whether that's actually a good behavior; but it is the historical, documented behavior and we've not had complaints about it.) If we have postinit.c use PGC_S_ENV_VAR for this purpose, then PGCLIENTENCODING will stop working because it will always be overridden from the database encoding, because that setting will be applied later with the same priority level. My conclusion about all this is that we really need to invent another GucSource value falling between PGC_S_DEFAULT and PGC_S_ENV_VAR, called perhaps PGC_S_DYNAMIC_DEFAULT, for the purpose of denoting values that are defaults in terms of the precedence pecking order but are not simply the hard-wired boot values. There's no real need for clients to see the difference, so we could have the external representation in pg_settings be "default" for both, but guc.c really needs to be aware of which settings are truly boot values and which are not. Comments? regards, tom lane
pgsql-hackers by date: