diff options
author | Andrew Morrow <acm@mongodb.com> | 2016-03-15 16:57:18 -0400 |
---|---|---|
committer | Andrew Morrow <acm@mongodb.com> | 2016-03-17 11:34:38 -0400 |
commit | 08f686baf91c9bf201d5a98ab7a1d93c1697a690 (patch) | |
tree | 7786d1b98e4975e2341c9f3908204a55bef50e91 | |
parent | 31701cb45e15c8c6cd7f89232c04893aad7565fe (diff) | |
download | mongo-08f686baf91c9bf201d5a98ab7a1d93c1697a690.tar.gz |
SERVER-22974 Ensure single threaded initialization of std::cout
-rw-r--r-- | src/mongo/logger/console.cpp | 24 |
1 files changed, 23 insertions, 1 deletions
diff --git a/src/mongo/logger/console.cpp b/src/mongo/logger/console.cpp index d2f4cdc6ac8..ea8bd299e1d 100644 --- a/src/mongo/logger/console.cpp +++ b/src/mongo/logger/console.cpp @@ -31,6 +31,8 @@ #include <iostream> +#include "mongo/base/init.h" + #ifdef _WIN32 #include <io.h> #endif @@ -225,10 +227,30 @@ std::ostream* getWindowsOutputStream() { std::ostream* windowsOutputStream = getWindowsOutputStream(); #endif // defined(_WIN32) +// This initializer causes a Console object to be constructed, which, +// in turn, causes std::ios_base::Init::Init to be called from a +// single threaded context, ensuring that std::cout is prepared in a +// single threaded context and available for all TUs. This is safe +// even for TUs that do not include <iostream>, since either the call +// to Console() here is the first call to that constructor, or the +// first logging call writing via the Console will happen elsewhere in +// the initalizer chain. +MONGO_INITIALIZER(EnsureIosBaseInitConstructed)(InitializerContext*) { + Console(); + return Status::OK(); +} + } // namespace Console::Console() : _consoleLock() { - const std::ios_base::Init initializeCout; + // Don't get clever and make this non-static. At least when using + // libc++, ios::base::Init::Init is not thread safe (see + // SERVER-22974). Instead, rely on C++11 magic statics to ensure + // that we create this at the right time. Some systems (like + // VS2013 and older), don't actually implement magic statics + // yet. But that is OK! We ensure that this is called from + // single-threaded context via a mongo initializer above. + static const std::ios_base::Init initializeCout; if (consoleMutex) { stdx::unique_lock<stdx::mutex> lk(*consoleMutex); |