[libcxx-commits] [libcxx] r361348 - Speculative fix for std stream destruction order on Windows.

Eric Fiselier via libcxx-commits libcxx-commits at lists.llvm.org
Tue May 21 20:45:49 PDT 2019


Author: ericwf
Date: Tue May 21 20:45:49 2019
New Revision: 361348

URL: http://llvm.org/viewvc/llvm-project?rev=361348&view=rev
Log:
Speculative fix for std stream destruction order on Windows.

The MSVC CRT uses TLS storage to implement per-thread locales.
This storage gets freed during program termination, and if we attempt
to do any io operations (like flushing the std streams) after this occurs
the program may abort.

This patch is a speculative fix for that issue.

The fix tries forcing the initialization of the locale TLS before
initializing the std streams. This should mean that the TLS is freed
after we destroy the streams.

Modified:
    libcxx/trunk/src/iostream.cpp

Modified: libcxx/trunk/src/iostream.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/src/iostream.cpp?rev=361348&r1=361347&r2=361348&view=diff
==============================================================================
--- libcxx/trunk/src/iostream.cpp (original)
+++ libcxx/trunk/src/iostream.cpp Tue May 21 20:45:49 2019
@@ -7,6 +7,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "__std_stream"
+#include "__locale"
 #include "string"
 #include "new"
 
@@ -78,8 +79,28 @@ __asm__("?wclog@" _LIBCPP_ABI_NAMESPACE_
 
 _LIBCPP_HIDDEN ios_base::Init __start_std_streams;
 
+// On Windows the TLS storage for locales needs to be initialized before we create
+// the standard streams, otherwise it may not be alive during program termination
+// when we flush the streams.
+static void force_locale_initialization() {
+#if defined(_LIBCPP_MSVCRT_LIKE)
+  static bool once = []() {
+    auto loc = newlocale(LC_ALL_MASK, "C", 0);
+    {
+        __libcpp_locale_guard g(loc); // forces initialization of locale TLS
+        ((void)g);
+    }
+    freelocale(loc);
+    return true;
+  }();
+  ((void)once);
+#endif
+}
+
 ios_base::Init::Init()
 {
+    force_locale_initialization();
+
 #ifndef _LIBCPP_HAS_NO_STDIN
     istream* cin_ptr  = ::new(cin)  istream(::new(__cin)  __stdinbuf <char>(stdin, &mb_cin));
     wistream* wcin_ptr  = ::new(wcin)  wistream(::new(__wcin)  __stdinbuf <wchar_t>(stdin, &mb_wcin));




More information about the libcxx-commits mailing list