Boost logo

Boost-Commit :

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;
   }
 


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk