-
-
Notifications
You must be signed in to change notification settings - Fork 196
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
Working around a problem with msvcrt and setlocale
#459
Comments
Thanks for the detailed bug report and analysis!
To set the expectations right here, it's not so much that this toolchain is designed to work with msvcrt; I try to make sure that configuration works, but it's definitely a second priority for the toolchain. And within llvm-mingw, I keep a fairly strict upstream-only/no-patches policy; I don't patch the sources from llvm-project/mingw-w64, but make sure to do fixes upstream - so they can benefit all distributions. (But when needed, I can do tweaks in how the code is built.) Specific workarounds for msvcrt.dll are, unfortunately, in a bit of a tricky spot wrt that though. Is this issue only present with msvcrt by design, or is it possible that UCRT could have similar issues as well, just not as easy to trigger? Does Avoiding calling It could in theory be possible to add wrappers in mingw-w64, to make I browsed https://devblogs.microsoft.com/oldnewthing/20120105-00/?p=8683 (which was referenced from https://devblogs.microsoft.com/oldnewthing/20120106-00/?p=8663 which you linked); when we're exiting the process we shouldn't be doing anything at all. But doesn't that also mean that we shouldn't be running any C++ destructors at all? Or put even further, that we shouldn't be running any atexit()-handlers or similar? Or do they run first, before we enter the "process is terminating" state? Does it make any difference here, if libc++ is linked statically or dynamically? It somewhat changes the execution order of destructors, IIRC. |
I think the thing is that you should prefer |
The message box behavior is part of msvcrt. I just tried UCRT now, the behavior looks consistent unlike msvcrt, but slightly different - if I use That's also what Raymond is saying in a follow-up blog post:
The above is for exes. With a dll it's more tricky to reproduce, as the destruction order depends on the load order of the DLLs, so to test whether a destructor runs or is aborted, I need to make sure the crt dll is loaded after the test dll. I tested it with an additional MSVC dll and it seems similarly problematic with msvcrt. UCRT has a similar problem if allocations are forced to fail - it aborts the process shutdown. At least it doesn't trigger a message box. The stack is without symbols, but
To summarize, in case of inability to allocate on process shutdown:
The function exists and has an implementation (e.g. here for some version) so I assume it works at least to some extent.
Yes, depending on why it's being used. If, for example, it's necessary to handle some strings or file names to flush data to disk/stdout, it might be justified.
I assume you're thinking: char* setlocale_wrapper(int category, const char* locale) {
if (RtlDllShutdownInProgress()) {
return NULL;
}
return setlocale(category, locale);
} That means
According to C++ it seems that destructors for global and static variables must be called. Raymond has a blog post about it as well, and a follow-up I already linked. "Or do they run first, before we enter the "process is terminating" state?" - the answer seems to be yes for exes, and no for dlls which are still expected run destructors in the "process is terminating" state.
My experience so far is only with a dynamically-linked libc++. The behavior is likely to be different with a statically-linked libc++, as in my tests the destruction flow starts with libc++.dll's |
In the case of an exe, yes. My problem was with loading a dll into a process that I don't control. So it's bad if my dll starts disrupting another program's cleanup flow, and it's especially bad if it causes a message box to show up when the process shuts down. |
I also posted a suggestion for UCRT to avoid freeing the per-thread data on process shutdown, which will make this issue much less likely. |
I wrote here in detail about a nasty problem I encountered with
msvcrt
: llvm/llvm-project#110954The short version is that if allocation fails while calling
setlocale
, which may happen in Windows during process shutdown regardless of memory availability,msvcrt
shows a message box and terminates the process, both of which are pretty bad.I'm not sure how the libc++ maintainers will react to the issue I created, I won't be surprised if they'll decide it's out of scope and an
msvcrt
problem. Since this toolchain is designed to work withmsvcrt
, perhaps a workaround can be added in the toolchain or its version of libc++. For example,setlocale
can be wrapped by something like:Unfortunately
_getptd_noexit
isn't exported bymsvcrt
, so the actual implementation must be different._get_errno
always returnsENOMEM
in this case, and_set_errno
always fails withENOMEM
, so an actual implementation can be:It's not the most elegant solution but it solves a real problem.
What do you think? Any other ideas?
Thanks, and thank you for this project.
The text was updated successfully, but these errors were encountered: