abort() in vsnprintf with MIMALLOC_VERBOSE=1, threads, and setlocale (Windows)
On Windows, If MIMALLOC_VERBOSE=1 environment variable is set, and a thread is created after setlocale(), then thread initialization code crashes with stacktrace below. Apparently, it seems that ucrtbase.dll is expecting/missing some thread-local locale-related variable, when its vsnprintf() is called. Also, debug CRT does not abort, only optimized version does.
I can reproduce with the below code, compiled RelWithDebInfo or Release (or MinSizeRel), with mimalloc malloc override is used.
#include <windows.h>
#include <stdio.h>
#include <process.h>
#include <locale.h>
unsigned int __stdcall thread_func(void*)
{
printf("In second thread...\n");
return 0;
}
int main()
{
HANDLE hThread;
unsigned int threadID;
setlocale(LC_ALL, "en_US.UTF8");
hThread = (HANDLE)_beginthreadex(NULL, 0, &thread_func, NULL, 0, &threadID);
WaitForSingleObject(hThread, INFINITE);
CloseHandle(hThread);
}
Stacktrace:
1 ucrtbase.dll!abort
2 ucrtbase.dll!__crt_cached_ptd_host::update_locale_slow
3 ucrtbase.dll!__crt_stdio_output::output_processor<char,__crt_stdio_output::string_output_adapter
Looking at the stacktrace, it seems that ucrtbase.dll's function __stdio_common_vsprintf is called inside ucrtbase.dll's DllMain function ucrtbase.dll!DllMainDispatch(). Not sure how safe that is. Perhaps it tries to use thread local storage which is not initialized yet. An alternative could be a self-written locale-unaware minimal version of vsnprintf, or using _vsnprintf exported function by ntdll.dll.
This issue seems will be fixed in the next release: #740
@portsip , thanks. #740 is still open, but now there is a repro for @daanx at least
You can check the dev branch, there has the commits for this issue, but not merge to master yet.