summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHenrik Edin <henrik.edin@mongodb.com>2020-02-24 11:19:20 -0500
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2020-02-26 22:09:44 +0000
commit95a345cc3f19a4762c68a40c7dd283ba0772ee11 (patch)
tree96fed9d0fdf1e04568cc99df8fc7285722796e4b
parentb88b28fccb697a020368c6a056f9987e4ff91206 (diff)
downloadmongo-95a345cc3f19a4762c68a40c7dd283ba0772ee11.tar.gz
SERVER-46008 Fix so logging works during global shutdown
-rw-r--r--src/mongo/logv2/log_domain_global.cpp43
-rw-r--r--src/mongo/logv2/log_manager.cpp4
-rw-r--r--src/mongo/logv2/log_source.h11
-rw-r--r--src/mongo/logv2/log_test_v2.cpp18
4 files changed, 60 insertions, 16 deletions
diff --git a/src/mongo/logv2/log_domain_global.cpp b/src/mongo/logv2/log_domain_global.cpp
index 7b8e117fa02..000ed72ffe3 100644
--- a/src/mongo/logv2/log_domain_global.cpp
+++ b/src/mongo/logv2/log_domain_global.cpp
@@ -68,6 +68,8 @@ struct LogDomainGlobal::Impl {
const ConfigurationOptions& config() const;
+ LogSource& source();
+
LogDomainGlobal& _parent;
LogComponentSettings _settings;
ConfigurationOptions _config;
@@ -76,6 +78,9 @@ struct LogDomainGlobal::Impl {
#ifndef _WIN32
boost::shared_ptr<boost::log::sinks::unlocked_sink<SyslogBackend>> _syslogSink;
#endif
+ AtomicWord<int32_t> activeSourceThreadLocals{0};
+ LogSource shutdownLogSource{&_parent, true};
+ bool isInShutdown{false};
};
LogDomainGlobal::Impl::Impl(LogDomainGlobal& parent) : _parent(parent) {
@@ -96,6 +101,10 @@ LogDomainGlobal::Impl::Impl(LogDomainGlobal& parent) : _parent(parent) {
// Set default configuration
invariant(configure({}).isOK());
+
+ // Make a call to source() to make sure the internal thread_local is created as early as
+ // possible and thus destroyed as late as possible.
+ source();
}
Status LogDomainGlobal::Impl::configure(LogDomainGlobal::ConfigurationOptions const& options) {
@@ -214,6 +223,36 @@ Status LogDomainGlobal::Impl::rotate(bool rename, StringData renameSuffix) {
return Status::OK();
}
+LogSource& LogDomainGlobal::Impl::source() {
+ // Use a thread_local logger so we don't need to have locking. thread_locals are destroyed
+ // before statics so keep track of number of thread_locals we have active and if this code
+ // is hit when it is zero then we are in shutdown and can use a global LogSource that does
+ // not provide synchronization instead.
+ class SourceCache {
+ public:
+ SourceCache(Impl* domain) : _domain(domain), _source(&domain->_parent) {
+ _domain->activeSourceThreadLocals.addAndFetch(1);
+ }
+ ~SourceCache() {
+ if (_domain->activeSourceThreadLocals.subtractAndFetch(1) == 0) {
+ _domain->isInShutdown = true;
+ }
+ }
+
+ LogSource& source() {
+ return _source;
+ }
+
+ private:
+ Impl* _domain;
+ LogSource _source;
+ };
+ thread_local SourceCache cache(this);
+ if (isInShutdown)
+ return shutdownLogSource;
+ return cache.source();
+}
+
LogDomainGlobal::LogDomainGlobal() {
_impl = std::make_unique<Impl>(*this);
}
@@ -221,9 +260,7 @@ LogDomainGlobal::LogDomainGlobal() {
LogDomainGlobal::~LogDomainGlobal() {}
LogSource& LogDomainGlobal::source() {
- // Use a thread_local logger so we don't need to have locking
- thread_local LogSource lg(this);
- return lg;
+ return _impl->source();
}
diff --git a/src/mongo/logv2/log_manager.cpp b/src/mongo/logv2/log_manager.cpp
index c532989b5d7..8f8453417e2 100644
--- a/src/mongo/logv2/log_manager.cpp
+++ b/src/mongo/logv2/log_manager.cpp
@@ -51,8 +51,8 @@ LogManager::LogManager() {
LogManager::~LogManager() {}
LogManager& LogManager::global() {
- static LogManager globalLogManager;
- return globalLogManager;
+ static LogManager* globalLogManager = new LogManager();
+ return *globalLogManager;
}
LogDomain& LogManager::getGlobalDomain() {
diff --git a/src/mongo/logv2/log_source.h b/src/mongo/logv2/log_source.h
index 25eea5c36b4..99269bcdba2 100644
--- a/src/mongo/logv2/log_source.h
+++ b/src/mongo/logv2/log_source.h
@@ -57,7 +57,7 @@ private:
basic_logger<char, LogSource, boost::log::sources::single_thread_model>;
public:
- LogSource(const LogDomain::Internal* domain)
+ explicit LogSource(const LogDomain::Internal* domain, bool isShutdown)
: _domain(domain),
_severity(LogSeverity::Log()),
_component(LogComponent::kDefault),
@@ -73,11 +73,14 @@ public:
add_attribute_unlocked(attributes::timeStamp(), boost::log::attributes::make_function([]() {
return Date_t::now();
}));
- add_attribute_unlocked(
- attributes::threadName(),
- boost::log::attributes::make_function([]() { return getThreadName(); }));
+ add_attribute_unlocked(attributes::threadName(),
+ boost::log::attributes::make_function([isShutdown]() {
+ return isShutdown ? "shutdown"_sd : getThreadName();
+ }));
}
+ explicit LogSource(const LogDomain::Internal* domain) : LogSource(domain, false) {}
+
boost::log::record open_record(int32_t id,
LogSeverity severity,
LogComponent component,
diff --git a/src/mongo/logv2/log_test_v2.cpp b/src/mongo/logv2/log_test_v2.cpp
index 0da56af42ea..12a592975d9 100644
--- a/src/mongo/logv2/log_test_v2.cpp
+++ b/src/mongo/logv2/log_test_v2.cpp
@@ -163,10 +163,10 @@ BSONObj toBSON(const TypeWithNonMemberFormatting&) {
return builder.obj();
}
-class LogDuringInitTester {
+class LogDuringInitShutdownTester {
public:
- LogDuringInitTester() {
- std::vector<std::string> lines;
+ LogDuringInitShutdownTester() {
+
auto sink = LogCaptureBackend::create(lines);
sink->set_filter(ComponentSettingsFilter(LogManager::global().getGlobalDomain(),
LogManager::global().getGlobalSettings()));
@@ -174,13 +174,17 @@ public:
boost::log::core::get()->add_sink(sink);
LOGV2(20001, "log during init");
- ASSERT(lines.back() == "log during init");
-
- boost::log::core::get()->remove_sink(sink);
+ ASSERT_EQUALS(lines.back(), "log during init");
}
+ ~LogDuringInitShutdownTester() {
+ LOGV2(4600800, "log during shutdown");
+ ASSERT_EQUALS(lines.back(), "log during shutdown");
+ }
+
+ std::vector<std::string> lines;
};
-LogDuringInitTester logDuringInit;
+LogDuringInitShutdownTester logDuringInitAndShutdown;
TEST_F(LogTestV2, Basic) {
std::vector<std::string> lines;