Bruno Haible <[EMAIL PROTECTED]> writes: > Simon Josefsson wrote: >> Any objections to installing this patch? > > Yes. I think it's a shame to return a non-POSIX-compliant result if there > are better possibilities. The appended patch is in my queue for a few days; > I'm meaning to test it a little more before I commit it.
Thanks. >> I searched a little, but could not find any thread-safe replacement >> for localeconv standardized anywhere, so I guess disabling it is the >> only option. > > There are at least two other options: > - Use nl_langinfo. nl_langinfo is not documented to be thread-safe, but > since it only returns constant strings that don't depend on any > parameter except the locale, it's likely that most implementors will > have the strings precomputed in some libc-private storage. Actually, nl_langinfo is documented to need not be thread-safe: http://www.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_09.html The documentation for the function suggests that the returned pointer may be to static data that can be overwritten by the next call. A valid implementation may be to copy the data to be returned into a fixed static buffer. For me, this too is a non-starter, and I'd prefer to disable use of any potentially thread-unsafe functions. I suggest the patch below. > - Establish a table of the decimal-point character for all locales in the > system at configuration time. Store them in a C file that presents a > MT-safe API for accessing it. That would be another solution, although I don't have time to work on it. One idea may be to create a module "decimal_point" -- the code to get the locale aware decimal point is now somewhat complicated. Alternatively, propose a nl_langinfo_r interface that is guaranteed to be thread safe. Btw, can we use the system's native sprintf to get the locale-aware decimal point in a thread-safe way? sprintf is guaranteed to be thread-safe, I believe. /Simon --- vasnprintf.c 27 Mar 2007 12:12:41 +0200 1.36 +++ vasnprintf.c 27 Mar 2007 12:32:20 +0200 @@ -34,14 +34,16 @@ # include "vasnprintf.h" #endif +#if !THREAD_UNSAFE #include <locale.h> /* localeconv() */ +#endif #include <stdio.h> /* snprintf(), sprintf() */ #include <stdlib.h> /* abort(), malloc(), realloc(), free() */ #include <string.h> /* memcpy(), strlen() */ #include <errno.h> /* errno */ #include <limits.h> /* CHAR_BIT */ #include <float.h> /* DBL_MAX_EXP, LDBL_MAX_EXP */ -#if HAVE_NL_LANGINFO +#if !THREAD_UNSAFE && HAVE_NL_LANGINFO # include <langinfo.h> #endif #if WIDE_CHAR_VERSION @@ -511,6 +513,7 @@ || mantissa > 0.0L || precision > 0) { const char *point; +# if THREAD_UNSAFE /* Prefer nl_langinfo() over localeconv(), since the latter is not multithread- safe. */ @@ -519,6 +522,9 @@ # else point = localeconv () -> decimal_point; # endif +# else + point = "."; +# endif /* The decimal point is always a single byte: either '.' or ','. */ *p++ = (point[0] != '\0' ? point[0] : '.'); @@ -668,6 +674,7 @@ || mantissa > 0.0 || precision > 0) { const char *point; +# if THREAD_UNSAFE /* Prefer nl_langinfo() over localeconv(), since the latter is not multithread- safe. */ @@ -676,6 +683,9 @@ # else point = localeconv () -> decimal_point; # endif +# else + point = "."; +# endif /* The decimal point is always a single byte: either '.' or ','. */ *p++ = (point[0] != '\0' ? point[0] : '.');