[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