aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNoah Misch <noah@leadboat.com>2015-01-07 22:34:57 -0500
committerNoah Misch <noah@leadboat.com>2015-01-07 22:35:16 -0500
commit05bb4fcad427b625e099517d76a62c6594806507 (patch)
tree7e9375b805cf2ce9c6d2931f9f55e2fbde77b26b
parent616830052ba3ed8abc52ba215f53d55f8413eae9 (diff)
downloadpostgresql-05bb4fcad427b625e099517d76a62c6594806507.tar.gz
postgresql-05bb4fcad427b625e099517d76a62c6594806507.zip
Always set the six locale category environment variables in main().
Typical server invocations already achieved that. Invalid locale settings in the initial postmaster environment interfered, as could malloc() failure. Setting "LC_MESSAGES=pt_BR.utf8 LC_ALL=invalid" in the postmaster environment will now choose C-locale messages, not Brazilian Portuguese messages. Most localized programs, including all PostgreSQL frontend executables, do likewise. Users are unlikely to observe changes involving locale categories other than LC_MESSAGES. CheckMyDatabase() ensures that we successfully set LC_COLLATE and LC_CTYPE; main() sets the remaining three categories to locale "C", which almost cannot fail. Back-patch to 9.0 (all supported versions).
-rw-r--r--src/backend/main/main.c38
1 files changed, 28 insertions, 10 deletions
diff --git a/src/backend/main/main.c b/src/backend/main/main.c
index 138963b55f4..e2bdee890c8 100644
--- a/src/backend/main/main.c
+++ b/src/backend/main/main.c
@@ -51,6 +51,7 @@ const char *progname;
static void startup_hacks(const char *progname);
+static void init_locale(int category, const char *locale);
static void help(const char *progname);
static void check_root(const char *progname);
static char *get_current_username(const char *progname);
@@ -122,31 +123,31 @@ main(int argc, char *argv[])
char *env_locale;
if ((env_locale = getenv("LC_COLLATE")) != NULL)
- pg_perm_setlocale(LC_COLLATE, env_locale);
+ init_locale(LC_COLLATE, env_locale);
else
- pg_perm_setlocale(LC_COLLATE, "");
+ init_locale(LC_COLLATE, "");
if ((env_locale = getenv("LC_CTYPE")) != NULL)
- pg_perm_setlocale(LC_CTYPE, env_locale);
+ init_locale(LC_CTYPE, env_locale);
else
- pg_perm_setlocale(LC_CTYPE, "");
+ init_locale(LC_CTYPE, "");
}
#else
- pg_perm_setlocale(LC_COLLATE, "");
- pg_perm_setlocale(LC_CTYPE, "");
+ init_locale(LC_COLLATE, "");
+ init_locale(LC_CTYPE, "");
#endif
#ifdef LC_MESSAGES
- pg_perm_setlocale(LC_MESSAGES, "");
+ init_locale(LC_MESSAGES, "");
#endif
/*
* We keep these set to "C" always, except transiently in pg_locale.c; see
* that file for explanations.
*/
- pg_perm_setlocale(LC_MONETARY, "C");
- pg_perm_setlocale(LC_NUMERIC, "C");
- pg_perm_setlocale(LC_TIME, "C");
+ init_locale(LC_MONETARY, "C");
+ init_locale(LC_NUMERIC, "C");
+ init_locale(LC_TIME, "C");
/*
* Now that we have absorbed as much as we wish to from the locale
@@ -279,6 +280,23 @@ startup_hacks(const char *progname)
/*
+ * Make the initial permanent setting for a locale category. If that fails,
+ * perhaps due to LC_foo=invalid in the environment, use locale C. If even
+ * that fails, perhaps due to out-of-memory, the entire startup fails with it.
+ * When this returns, we are guaranteed to have a setting for the given
+ * category's environment variable.
+ */
+static void
+init_locale(int category, const char *locale)
+{
+ if (pg_perm_setlocale(category, locale) == NULL &&
+ pg_perm_setlocale(category, "C") == NULL)
+ elog(FATAL, "could not adopt C locale");
+}
+
+
+
+/*
* Help display should match the options accepted by PostmasterMain()
* and PostgresMain().
*/