]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Use thread-safe nl_langinfo_l(), not nl_langinfo().
authorThomas Munro <tmunro@postgresql.org>
Tue, 13 Aug 2024 10:27:16 +0000 (22:27 +1200)
committerThomas Munro <tmunro@postgresql.org>
Tue, 13 Aug 2024 10:34:53 +0000 (22:34 +1200)
This gets rid of some setlocale() calls.  The remaining call to
setlocale() in pg_get_encoding_from_locale() is a query of the name
of the current locale when none was provided (in a multi-threaded future
that would need more work).

All known non-Windows targets have nl_langinfo_l(), from POSIX 2008, and
for Windows we already do something thread-safe.

Reviewed-by: Heikki Linnakangas <hlinnaka@iki.fi>
Discussion: https://postgr.es/m/CA%2BhUKGJqVe0%2BPv9dvC9dSums_PXxGo9SWcxYAMBguWJUGbWz-A%40mail.gmail.com

src/port/chklocale.c

index a0cc52c38df77b38192c062c4a775fb09f53e3da..14d0e2c55794bfcff6daac04bf4ef58cae358f4a 100644 (file)
@@ -306,63 +306,34 @@ pg_get_encoding_from_locale(const char *ctype, bool write_message)
        char       *sys;
        int                     i;
 
-       /* Get the CODESET property, and also LC_CTYPE if not passed in */
-       if (ctype)
-       {
-               char       *save;
-               char       *name;
-
-               /* If locale is C or POSIX, we can allow all encodings */
-               if (pg_strcasecmp(ctype, "C") == 0 ||
-                       pg_strcasecmp(ctype, "POSIX") == 0)
-                       return PG_SQL_ASCII;
-
-               save = setlocale(LC_CTYPE, NULL);
-               if (!save)
-                       return -1;                      /* setlocale() broken? */
-               /* must copy result, or it might change after setlocale */
-               save = strdup(save);
-               if (!save)
-                       return -1;                      /* out of memory; unlikely */
-
-               name = setlocale(LC_CTYPE, ctype);
-               if (!name)
-               {
-                       free(save);
-                       return -1;                      /* bogus ctype passed in? */
-               }
-
 #ifndef WIN32
-               sys = nl_langinfo(CODESET);
-               if (sys)
-                       sys = strdup(sys);
-#else
-               sys = win32_langinfo(name);
+       locale_t        loc;
 #endif
 
-               setlocale(LC_CTYPE, save);
-               free(save);
-       }
-       else
-       {
-               /* much easier... */
+       /* Get the CODESET property, and also LC_CTYPE if not passed in */
+       if (!ctype)
                ctype = setlocale(LC_CTYPE, NULL);
-               if (!ctype)
-                       return -1;                      /* setlocale() broken? */
 
-               /* If locale is C or POSIX, we can allow all encodings */
-               if (pg_strcasecmp(ctype, "C") == 0 ||
-                       pg_strcasecmp(ctype, "POSIX") == 0)
-                       return PG_SQL_ASCII;
+
+       /* If locale is C or POSIX, we can allow all encodings */
+       if (pg_strcasecmp(ctype, "C") == 0 ||
+               pg_strcasecmp(ctype, "POSIX") == 0)
+               return PG_SQL_ASCII;
+
 
 #ifndef WIN32
-               sys = nl_langinfo(CODESET);
-               if (sys)
-                       sys = strdup(sys);
+       loc = newlocale(LC_CTYPE_MASK, ctype, (locale_t) 0);
+       if (loc == (locale_t) 0)
+               return -1;                              /* bogus ctype passed in? */
+
+       sys = nl_langinfo_l(CODESET, loc);
+       if (sys)
+               sys = strdup(sys);
+
+       freelocale(loc);
 #else
-               sys = win32_langinfo(ctype);
+       sys = win32_langinfo(ctype);
 #endif
-       }
 
        if (!sys)
                return -1;                              /* out of memory; unlikely */