Changeset 14533


Ignore:
Timestamp:
Jun 1, 2015, 5:25:14 AM (6 years ago)
Author:
mikedld
Message:

#5851: Use per-thread locale setup if possible

This prevents crashes on concurrent tr_variantFromBuf, tr_variantToBuf
and tr_variantGetReal use.

Location:
trunk
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/CMakeLists.txt

    r14515 r14533  
    382382    stdbool.h
    383383    sys/statvfs.h
    384     xfs/xfs.h)
     384    xfs/xfs.h
     385    xlocale.h)
    385386
    386387if(ENABLE_NLS)
     
    417418    strsep
    418419    syslog
     420    uselocale
    419421    valloc)
    420422
  • trunk/configure.ac

    r14520 r14533  
    107107AC_HEADER_TIME
    108108
    109 AC_CHECK_HEADERS([stdbool.h])
    110 AC_CHECK_FUNCS([iconv_open pread pwrite lrintf strlcpy daemon dirname basename canonicalize_file_name strcasecmp localtime_r fallocate64 posix_fallocate memmem strsep strtold syslog valloc getpagesize posix_memalign statvfs htonll ntohll mkdtemp])
     109AC_CHECK_HEADERS([stdbool.h xlocale.h])
     110AC_CHECK_FUNCS([iconv_open pread pwrite lrintf strlcpy daemon dirname basename canonicalize_file_name strcasecmp localtime_r fallocate64 posix_fallocate memmem strsep strtold syslog valloc getpagesize posix_memalign statvfs htonll ntohll mkdtemp uselocale])
    111111AC_PROG_INSTALL
    112112AC_PROG_MAKE_SET
  • trunk/libtransmission/variant.c

    r14521 r14533  
    88 */
    99
     10#if defined (HAVE_USELOCALE) && (!defined (_XOPEN_SOURCE) || _XOPEN_SOURCE < 700)
     11 #undef _XOPEN_SOURCE
     12 #define _XOPEN_SOURCE 700
     13#endif
     14
     15#if defined (HAVE_USELOCALE) && !defined (_GNU_SOURCE)
     16 #define _GNU_SOURCE
     17#endif
     18
    1019#include <assert.h>
    1120#include <errno.h>
     
    1827
    1928#include <locale.h> /* setlocale() */
     29
     30#if defined (HAVE_USELOCALE) && defined (HAVE_XLOCALE_H)
     31 #include <xlocale.h>
     32#endif
    2033
    2134#include <event2/buffer.h>
     
    3548**/
    3649
     50struct locale_context
     51{
     52#ifdef HAVE_USELOCALE
     53  locale_t new_locale;
     54  locale_t old_locale;
     55#else
     56#ifdef _WIN32
     57  int old_thread_config;
     58#endif
     59  int category;
     60  char old_locale[128];
     61#endif
     62};
     63
     64static void
     65use_numeric_locale (struct locale_context * context,
     66                    const char            * locale_name)
     67{
     68#ifdef HAVE_USELOCALE
     69
     70  context->new_locale = newlocale (LC_NUMERIC_MASK, locale_name, NULL);
     71  context->old_locale = uselocale (context->new_locale);
     72
     73#else
     74
     75#ifdef _WIN32
     76  context->old_thread_config = _configthreadlocale (_ENABLE_PER_THREAD_LOCALE);
     77#endif
     78
     79  context->category = LC_NUMERIC;
     80  tr_strlcpy (context->old_locale, setlocale (context->category, NULL), sizeof (context->old_locale));
     81  setlocale (context->category, locale_name);
     82
     83#endif
     84}
     85
     86static void
     87restore_locale (struct locale_context * context)
     88{
     89#ifdef HAVE_USELOCALE
     90
     91  uselocale (context->old_locale);
     92  freelocale (context->new_locale);
     93
     94#else
     95
     96  setlocale (context->category, context->old_locale);
     97
     98#ifdef _WIN32
     99  _configthreadlocale (context->old_thread_config);
     100#endif
     101
     102#endif
     103}
     104
     105/***
     106****
     107***/
     108
    37109static bool
    38110tr_variantIsContainer (const tr_variant * v)
     
    302374    {
    303375      char * endptr;
    304       char locale[128];
     376      struct locale_context locale_ctx;
    305377      double d;
    306378
    307379      /* the json spec requires a '.' decimal point regardless of locale */
    308       tr_strlcpy (locale, setlocale (LC_NUMERIC, NULL), sizeof (locale));
    309       setlocale (LC_NUMERIC, "POSIX");
     380      use_numeric_locale (&locale_ctx, "C");
    310381      d  = strtod (getStr (v), &endptr);
    311       setlocale (LC_NUMERIC, locale);
     382      restore_locale (&locale_ctx);
    312383
    313384      if ((success = (getStr (v) != endptr) && !*endptr))
     
    10941165tr_variantToBuf (const tr_variant * v, tr_variant_fmt fmt)
    10951166{
    1096   char lc_numeric[128];
     1167  struct locale_context locale_ctx;
    10971168  struct evbuffer * buf = evbuffer_new();
    10981169
    10991170  /* parse with LC_NUMERIC="C" to ensure a "." decimal separator */
    1100   tr_strlcpy (lc_numeric, setlocale (LC_NUMERIC, NULL), sizeof (lc_numeric));
    1101   setlocale (LC_NUMERIC, "C");
     1171  use_numeric_locale (&locale_ctx, "C");
    11021172
    11031173  evbuffer_expand (buf, 4096); /* alloc a little memory to start off with */
     
    11191189
    11201190  /* restore the previous locale */
    1121   setlocale (LC_NUMERIC, lc_numeric);
     1191  restore_locale (&locale_ctx);
    11221192  return buf;
    11231193}
     
    12521322{
    12531323  int err;
    1254   char lc_numeric[128];
     1324  struct locale_context locale_ctx;
    12551325
    12561326  /* parse with LC_NUMERIC="C" to ensure a "." decimal separator */
    1257   tr_strlcpy (lc_numeric, setlocale (LC_NUMERIC, NULL), sizeof (lc_numeric));
    1258   setlocale (LC_NUMERIC, "C");
     1327  use_numeric_locale (&locale_ctx, "C");
    12591328
    12601329  switch (fmt)
     
    12711340
    12721341  /* restore the previous locale */
    1273   setlocale (LC_NUMERIC, lc_numeric);
     1342  restore_locale (&locale_ctx);
    12741343  return err;
    12751344}
Note: See TracChangeset for help on using the changeset viewer.