$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r76303 - trunk/libs/filesystem/v3/src
From: bdawes_at_[hidden]
Date: 2012-01-04 09:53:49
Author: bemandawes
Date: 2012-01-04 09:53:46 EST (Wed, 04 Jan 2012)
New Revision: 76303
URL: http://svn.boost.org/trac/boost/changeset/76303
Log:
Fix #4889, #6320, Locale codecvt_facet not thread safe on Windows. Move Windows, Mac OS X, locale and codecvt facet back to namespace scope. POSIX except OS X uses local static initialization (IE lazy) to ensure exceptions are catchable if environmental variables are misconfigured and to avoid use of locale("") if not actually used.
Text files modified: 
   trunk/libs/filesystem/v3/src/path.cpp |   119 ++++++++++++++++++++------------------- 
   1 files changed, 61 insertions(+), 58 deletions(-)
Modified: trunk/libs/filesystem/v3/src/path.cpp
==============================================================================
--- trunk/libs/filesystem/v3/src/path.cpp	(original)
+++ trunk/libs/filesystem/v3/src/path.cpp	2012-01-04 09:53:46 EST (Wed, 04 Jan 2012)
@@ -727,56 +727,55 @@
   //                              locale helpers                                        //
   //------------------------------------------------------------------------------------//
 
-  std::locale default_locale()
-  {
-#   ifdef BOOST_WINDOWS_API
-    std::locale global_loc = std::locale();
-    std::locale loc(global_loc, new windows_file_codecvt);
-    return loc;
-
-#   elif defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
-    // "All BSD system functions expect their string parameters to be in UTF-8 encoding
-    // and nothing else." See
-    // http://developer.apple.com/mac/library/documentation/MacOSX/Conceptual/BPInternational/Articles/FileEncodings.html
-    //
-    // "The kernel will reject any filename that is not a valid UTF-8 string, and it will
-    // even be normalized (to Unicode NFD) before stored on disk, at least when using HFS.
-    // The right way to deal with it would be to always convert the filename to UTF-8
-    // before trying to open/create a file." See
-    // http://lists.apple.com/archives/unix-porting/2007/Sep/msg00023.html
-    //
-    // "How a file name looks at the API level depends on the API. Current Carbon APIs
-    // handle file names as an array of UTF-16 characters; POSIX ones handle them as an
-    // array of UTF-8, which is why UTF-8 works well in Terminal. How it's stored on disk
-    // depends on the disk format; HFS+ uses UTF-16, but that's not important in most
-    // cases." See
-    // http://lists.apple.com/archives/applescript-users/2002/Sep/msg00319.html
-    //
-    // Many thanks to Peter Dimov for digging out the above references!
-
-    std::locale global_loc = std::locale();
-    std::locale loc(global_loc, new boost::filesystem::detail::utf8_codecvt_facet);
-    return loc;
-
-#   else  // Other POSIX
-
-    // ISO C calls std::locale("") "the locale-specific native environment", and this
-    // locale is the default for many POSIX-based operating systems such as Linux.
-
-    // std::locale("") construction can throw (if environmental variables LC_MESSAGES or
-    // or LANG are wrong, for example), so dynamic initialization is used to ensure
-    // that exceptions can be caught.
+#ifdef BOOST_WINDOWS_API
 
-    return std::locale("");
+  std::locale path_locale(std::locale(), new windows_file_codecvt); 
 
-#   endif
-  }
+  const std::codecvt<wchar_t, char, std::mbstate_t>*
+    codecvt_facet(&std::use_facet<std::codecvt<wchar_t, char, std::mbstate_t> >
+      (path_locale));
+
+#elif defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
+
+  // "All BSD system functions expect their string parameters to be in UTF-8 encoding
+  // and nothing else." See
+  // http://developer.apple.com/mac/library/documentation/MacOSX/Conceptual/BPInternational/Articles/FileEncodings.html
+  //
+  // "The kernel will reject any filename that is not a valid UTF-8 string, and it will
+  // even be normalized (to Unicode NFD) before stored on disk, at least when using HFS.
+  // The right way to deal with it would be to always convert the filename to UTF-8
+  // before trying to open/create a file." See
+  // http://lists.apple.com/archives/unix-porting/2007/Sep/msg00023.html
+  //
+  // "How a file name looks at the API level depends on the API. Current Carbon APIs
+  // handle file names as an array of UTF-16 characters; POSIX ones handle them as an
+  // array of UTF-8, which is why UTF-8 works well in Terminal. How it's stored on disk
+  // depends on the disk format; HFS+ uses UTF-16, but that's not important in most
+  // cases." See
+  // http://lists.apple.com/archives/applescript-users/2002/Sep/msg00319.html
+  //
+  // Many thanks to Peter Dimov for digging out the above references!
+
+  std::locale path_locale(std::locale(),
+                          new boost::filesystem::detail::utf8_codecvt_facet);
+
+  const std::codecvt<wchar_t, char, std::mbstate_t>*
+    codecvt_facet(&std::use_facet<std::codecvt<wchar_t, char, std::mbstate_t> >
+      (path_locale));
+
+#else  // Other POSIX
+
+  // ISO C calls std::locale("") "the locale-specific native environment", and this
+  // locale is the default for many POSIX-based operating systems such as Linux.
+
+  // std::locale("") construction can throw (if environmental variables LC_MESSAGES or
+  // or LANG are wrong, for example), so lazy initialization is used to ensure
+  // that exceptions occur after main() starts and so can be caught.
 
-  std::locale& path_locale()
-  {
-    static std::locale loc(default_locale());
-    return loc;
-  }
+  std::locale path_locale;  // initialized by path::wchar_t_codecvt_facet() below
+  const std::codecvt<wchar_t, char, std::mbstate_t>* codecvt_facet;  // ditto
+
+# endif
 
 }  // unnamed namespace
 
@@ -789,21 +788,25 @@
 namespace filesystem3
 {
 
-  const path::codecvt_type *& path::wchar_t_codecvt_facet()
+  const path::codecvt_type*& path::wchar_t_codecvt_facet()
   {
-   static const std::codecvt<wchar_t, char, std::mbstate_t> *
-     facet(
-       &std::use_facet<std::codecvt<wchar_t, char, std::mbstate_t> >
-        (path_locale()));
-   return facet;
+#   if defined(BOOST_POSIX_API) && \
+      !(defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__))
+      // A local static initialized by calling path::imbue ensures that std::locale(""),
+      // which may throw, is called only if path_locale and condecvt_facet will actually
+      // be used. Thus misconfigured environmental variables will only cause an
+      // exception if a valid std::locale("") is actually needed.
+      static std::locale posix_lazy_initialization(path::imbue(std::locale("")));
+#   endif
+    return codecvt_facet;
   }
 
-  std::locale path::imbue(const std::locale & loc)
+  std::locale path::imbue(const std::locale& loc)
   {
-    std::locale temp(path_locale());
-    path_locale() = loc;
-    wchar_t_codecvt_facet() =
-      &std::use_facet<std::codecvt<wchar_t, char, std::mbstate_t> >(path_locale());
+    std::locale temp(path_locale);
+    path_locale = loc;
+    codecvt_facet =
+      &std::use_facet<std::codecvt<wchar_t, char, std::mbstate_t> >(path_locale);
     return temp;
   }