Print this page
Thread safety fixes.
*** 41,50 ****
--- 41,51 ----
#include <locale.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdio.h>
+ #include "mtlib.h"
#include "collate.h"
#include "lnumeric.h" /* for struct lc_numeric */
#include "lctype.h" /* for struct lc_ctype */
#include "setlocale.h"
#include "../i18n/_loc_path.h"
*** 57,71 ****
char *_PathLocale = _DFLT_LOC_PATH;
static char *current_locale(locale_t, int);
static void install_legacy(locale_t, int);
char *
setlocale(int category, const char *locname)
{
! locale_t oldloc;
! locale_t newloc;
int mask;
if (category < 0 || category > LC_ALL) {
errno = EINVAL;
return (NULL);
--- 58,75 ----
char *_PathLocale = _DFLT_LOC_PATH;
static char *current_locale(locale_t, int);
static void install_legacy(locale_t, int);
+ static mutex_t setlocale_lock = DEFAULTMUTEX;
+ static locale_t setlocale_list = NULL;
+
char *
setlocale(int category, const char *locname)
{
! locale_t loc;
! locale_t srch;
int mask;
if (category < 0 || category > LC_ALL) {
errno = EINVAL;
return (NULL);
*** 72,99 ****
}
if (locname == NULL)
return (current_locale(___global_locale, category));
- if ((oldloc = duplocale(___global_locale)) == NULL)
- return (NULL);
-
mask = (category == LC_ALL ? LC_ALL_MASK : (1 << category));
! newloc = newlocale(mask, locname, oldloc);
! if (newloc == NULL) {
! freelocale(oldloc);
return (NULL);
}
! oldloc = ___global_locale;
! ___global_locale = newloc;
! install_legacy(newloc, mask);
! freelocale(oldloc);
! return (current_locale(newloc, category));
}
static char *
current_locale(locale_t loc, int cat)
{
--- 76,125 ----
}
if (locname == NULL)
return (current_locale(___global_locale, category));
mask = (category == LC_ALL ? LC_ALL_MASK : (1 << category));
! loc = newlocale(mask, locname, NULL);
! if (loc == NULL) {
return (NULL);
}
! /*
! * This next logic looks to see if we have ever used the same locale
! * settings before. If so, we reuse it. We avoid ever calling
! * freelocale() on a locale setting built up by setlocale, this
! * ensures that consumers (uselocale) will always be thread safe;
! * the actual locale data objects are never freed, and unique
! * locale objects are also never freed. We reuse to avoid leaking
! * memory in applications that call setlocale repeatedly.
! */
! lmutex_lock(&setlocale_lock);
! for (srch = setlocale_list; srch != NULL; srch = srch->next) {
! if (memcmp(srch->locdata, loc->locdata,
! sizeof (loc->locdata[0]) * LC_ALL) != 0) {
! continue;
! }
! break;
! }
! if (srch == NULL) {
! /* this is a new locale, save it for reuse later */
! loc->next = setlocale_list;
! setlocale_list = loc;
! } else {
! /* we already had it, toss the new, and use what we found */
! freelocale(loc);
! loc = srch;
! }
! ___global_locale = loc;
! install_legacy(loc, mask);
! lmutex_unlock(&setlocale_lock);
!
! return (current_locale(loc, category));
}
static char *
current_locale(locale_t loc, int cat)
{