[libcxx-commits] [libcxx] Avoid calling `setlocale` in `do_unshift` when unnecessary (PR #117153)

Michael Maltsev via libcxx-commits libcxx-commits at lists.llvm.org
Thu Nov 21 04:58:53 PST 2024


https://github.com/m417z created https://github.com/llvm/llvm-project/pull/117153

This is an attempt to mitigate #110954.

As part of the libc++.dll initialization, `static DoIOSInit` is initialized:
https://github.com/llvm/llvm-project/blob/5bdee35544eb21762857390014598748c64ad485/libcxx/src/iostream.cpp#L165-L167

When the dll is unloaded or on process shutdown, `DoIOSInit::~DoIOSInit` is called. It ends up calling `flush`:
https://github.com/llvm/llvm-project/blob/5bdee35544eb21762857390014598748c64ad485/libcxx/src/iostream.cpp#L159

Which calls `pubsync`:
https://github.com/llvm/llvm-project/blob/5bdee35544eb21762857390014598748c64ad485/libcxx/include/__ostream/basic_ostream.h#L659

Which ends up calling `do_unshift`:
https://github.com/llvm/llvm-project/blob/5bdee35544eb21762857390014598748c64ad485/libcxx/src/locale.cpp#L1475-L1479

Which, as can be seen, unconditionally calls `__locale::__wcrtomb`, which ends up calling `setlocale` via `__libcpp_locale_guard`.

All this means that `setlocale` is called on process shutdown even if `wcout` is never used, or even if nothing stream-related is used. Calling `setlocale` on process shutdown causes problems, as described in the mentioned issue.

This PR is an attempt to avoid calling `setlocale` in the vast majority of cases, when there's no output to be flushed. It's not a complete fix to the issue, but it will make it much less common, and it will at least allow to flush output manually to avoid the issue if streams are used.

>From 330b197dafc158e1586890ddf9bd1c64417514bf Mon Sep 17 00:00:00 2001
From: Michael Maltsev <4129781+m417z at users.noreply.github.com>
Date: Thu, 21 Nov 2024 14:29:19 +0200
Subject: [PATCH] Avoid calling setlocale in do_unshift when unnecessary

---
 libcxx/src/locale.cpp | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/libcxx/src/locale.cpp b/libcxx/src/locale.cpp
index a1e10401f0b299..5ecd99c53cd516 100644
--- a/libcxx/src/locale.cpp
+++ b/libcxx/src/locale.cpp
@@ -1475,6 +1475,8 @@ codecvt<wchar_t, char, mbstate_t>::result codecvt<wchar_t, char, mbstate_t>::do_
 codecvt<wchar_t, char, mbstate_t>::result codecvt<wchar_t, char, mbstate_t>::do_unshift(
     state_type& st, extern_type* to, extern_type* to_end, extern_type*& to_nxt) const {
   to_nxt = to;
+  if (std::mbsinit(&st))
+    return ok;
   extern_type tmp[MB_LEN_MAX];
   size_t n = __locale::__wcrtomb(tmp, intern_type(), &st, __l_);
   if (n == size_t(-1) || n == 0) // on error



More information about the libcxx-commits mailing list