bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: use of thread-unsafe localeconv in vasprintf


From: Simon Josefsson
Subject: Re: use of thread-unsafe localeconv in vasprintf
Date: Tue, 27 Mar 2007 12:41:40 +0200
User-agent: Gnus/5.110006 (No Gnus v0.6) Emacs/22.0.95 (gnu/linux)

Bruno Haible <address@hidden> 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] : '.');




reply via email to

[Prev in Thread] Current Thread [Next in Thread]