Search code examples
c++multithreadingc11setlocale

Undefined behavior with setlocale and multithreading?


CppRef states2016-12-13 09:00 UTC:

Because setlocale modifies global state which affects execution of locale-dependent functions, it is undefined behavior to call it from one thread, while another thread is executing any of the following functions: std::fprintf, std::isprint, std::iswdigit, std::localeconv, std::tolower, std::fscanf, std::ispunct, std::iswgraph, std::mblen, std::toupper, std::isalnum, std::isspace, std::iswlower, std::mbstowcs, std::towlower, std::isalpha, std::isupper, std::iswprint, std::mbtowc, std::towupper, std::isblank, std::iswalnum, std::iswpunct, std::setlocale, std::wcscoll, std::iscntrl, std::iswalpha, std::iswspace, std::strcoll, std::wcstod, std::isdigit, std::iswblank, std::iswupper, std::strerror, std::wcstombs, std::isgraph, std::iswcntrl, std::iswxdigit, std::strtod, std::wcsxfrm, std::islower, std::iswctype, std::isxdigit.

This info seems ... surprising at least.

I know that it affects global state, I'm fine with that (otherwise I'd be using a different method to change locale).

I always assumed though (and I think VC++ at least implements it that way) that setlocale is thread safe vs. the functions that use locale.

Do the newer C++ standards (and C?) (that actually incorporate threading at all) say anything about this?


Solution

  • For C11 the standard clearly states

    A call to the setlocale function may introduce a data race with other calls to the setlocale function or with calls to functions that are affected by the current locale. The implementation shall behave as if no library function calls the setlocale function.

    So, no, setlocale can not be supposed to be threadsafe, unless your platform makes additional guarantees.

    Since this is a C library thing to which C++ usually just refers, my expectation would be that it is the same there.

    In practical terms this means that you should only use setlocale in the startup of a multi-threaded program, before you launch any supplementary threads.