-
Notifications
You must be signed in to change notification settings - Fork 15.2k
[libc++] Avoid calling setlocale in do_unshift when unnecessary
#117153
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
|
Thank you for submitting a Pull Request (PR) to the LLVM Project! This PR will be automatically labeled and the relevant teams will be notified. If you wish to, you can add reviewers by using the "Reviewers" section on this page. If this is not working for you, it is probably because you do not have write permissions for the repository. In which case you can instead tag reviewers by name in a comment by using If you have received no comments on your PR for a week, you can request a review by "ping"ing the PR by adding a comment “Ping”. The common courtesy "ping" rate is once a week. Please remember that you are asking for valuable time from other developers. If you have further questions, they may be answered by the LLVM GitHub User Guide. You can also ask questions in a comment on this PR, on the LLVM Discord or on the forums. |
|
@llvm/pr-subscribers-libcxx Author: Michael Maltsev (m417z) ChangesThis is an attempt to mitigate #110954. As part of the libc++.dll initialization, llvm-project/libcxx/src/iostream.cpp Lines 165 to 167 in 5bdee35
When the dll is unloaded or on process shutdown, llvm-project/libcxx/src/iostream.cpp Line 159 in 5bdee35
Which calls
Which ends up calling llvm-project/libcxx/src/locale.cpp Lines 1475 to 1479 in 5bdee35
Which, as can be seen, unconditionally calls All this means that This PR is an attempt to avoid calling Full diff: https://github.com/llvm/llvm-project/pull/117153.diff 1 Files Affected:
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
|
setlocale in do_unshift when unnecessarysetlocale in do_unshift when unnecessary
|
I wonder if we should remove the llvm-project/libcxx/include/fstream Lines 965 to 983 in c4d656a
The standard doesn't require such a call. [filebuf.virtuals]/19:
|
|
|
ldionne
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not the best person to review this PR because I'm not very well-versed in locales and all this multibyte character fun. But this seems correct to me based on cppreference's interpretation of the Standard, which is better than nothing:
If the encoding represented by this codecvt facet is state-dependent, and state represents a conversion state that is not the initial shift state, writes the characters necessary to return to the initial shift state.
The effects in the actual Standard don't mention this specifically but I assume this is obvious to anyone more familiar with this API.
It would be nice to get a short review from someone like @tahonermann or @mstorsjo.
Assuming this is functionally correct, I have no objection about short-circuiting in this function to minimize the impact of the linked bug.
|
Hopefully @tahonermann has time to look at this; I'm unfortunately not very familiar with this area. In particular, I don't quite follow how the PR description (which sounds very reasonable) maps to this piece of code - how |
|
@mstorsjo thanks for taking a look. This fix is mostly an educated guess based on my best understanding from skimming over the code. I hoped that this simple two-liner fix will either just work, or will get a trivial correction from somebody who's familiar with this area.
Maybe I'm completely off here (I wasn't familiar with this function prior to looking at this area), but from the description and the code example of this function, my best understanding is that
I figured that it doesn't really matter. If anything, it acts as an optimization for the common case, which might be significant or not depending on the implementation of Here, it was mentioned that a more complete fix would be to have some of the missing Windows string functions implemented:
Did you see this comment? Any thoughts about it? |
Ok, so this is only about flushing incomplete multibyte chars? Then I guess this may seem reasonable.
Ah, right - I never got around to commenting on it. Offhand I don't know of any good way to avoid that problem, short of manually implementing them. I believe that would require access to the internals of the existing functions in order to share code/logic with them, though, or then just write complete reimplementations from scratch. But I haven't spent any effort on researching this area. |
My thought was that replacing |
This is an attempt to mitigate #110954.
As part of the libc++.dll initialization,
static DoIOSInitis initialized:llvm-project/libcxx/src/iostream.cpp
Lines 165 to 167 in 5bdee35
When the dll is unloaded or on process shutdown,
DoIOSInit::~DoIOSInitis called. It ends up callingflush:llvm-project/libcxx/src/iostream.cpp
Line 159 in 5bdee35
Which calls
pubsync:llvm-project/libcxx/include/__ostream/basic_ostream.h
Line 659 in 5bdee35
Which ends up calling
do_unshift:llvm-project/libcxx/src/locale.cpp
Lines 1475 to 1479 in 5bdee35
Which, as can be seen, unconditionally calls
__locale::__wcrtomb, which ends up callingsetlocalevia__libcpp_locale_guard.All this means that
setlocaleis called on process shutdown even ifwcoutis never used, or even if nothing stream-related is used. Callingsetlocaleon process shutdown causes problems, as described in the mentioned issue.This PR is an attempt to avoid calling
setlocalein 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.