diff --git a/src/aws-cpp-sdk-core/source/utils/logging/AWSLogging.cpp b/src/aws-cpp-sdk-core/source/utils/logging/AWSLogging.cpp index 3163e19d9ca1..1709dcd7c1d6 100644 --- a/src/aws-cpp-sdk-core/source/utils/logging/AWSLogging.cpp +++ b/src/aws-cpp-sdk-core/source/utils/logging/AWSLogging.cpp @@ -14,8 +14,28 @@ using namespace Aws::Utils; using namespace Aws::Utils::Logging; -static std::shared_ptr AWSLogSystem(nullptr); -static std::shared_ptr OldLogger(nullptr); +namespace { + +// AWS clients owned by other globals can be destroyed after this translation +// unit's statics (static destruction order across translation units is +// unspecified) and still log through GetLogSystem() while unwinding. The flag +// is trivially destructible, so it stays readable until the very end of the +// process; once ~LoggingSet has cleared it, the accessors below behave as +// if no logger is installed instead of touching the destroyed shared_ptrs. +bool LoggingSetAlive = true; + +struct LoggingSet { + std::shared_ptr AWSLogSystem; + std::shared_ptr OldLogger; + + ~LoggingSet() { + LoggingSetAlive = false; + } +}; + +LoggingSet LogSet; + +} // anonymous namespace namespace Aws { @@ -24,7 +44,9 @@ namespace Utils namespace Logging { void InitializeAWSLogging(const std::shared_ptr &logSystem) { - AWSLogSystem = logSystem; + if (LoggingSetAlive) { + LogSet.AWSLogSystem = logSystem; + } } void ShutdownAWSLogging(void) { @@ -33,23 +55,31 @@ void ShutdownAWSLogging(void) { // so this is a hack to let all other threads finish their log statement after getting a LogSystem pointer // otherwise we would need to perform ref-counting on each logging statement std::this_thread::sleep_for(std::chrono::milliseconds(1)); - OldLogger.reset(); + if (LoggingSetAlive) { + LogSet.OldLogger.reset(); + } } LogSystemInterface *GetLogSystem() { - return AWSLogSystem.get(); + return LoggingSetAlive ? LogSet.AWSLogSystem.get() : nullptr; } void PushLogger(const std::shared_ptr &logSystem) { - OldLogger = AWSLogSystem; - AWSLogSystem = logSystem; + if (!LoggingSetAlive) { + return; + } + LogSet.OldLogger = LogSet.AWSLogSystem; + LogSet.AWSLogSystem = logSystem; } void PopLogger() { - AWSLogSystem = OldLogger; - OldLogger = nullptr; + if (!LoggingSetAlive) { + return; + } + LogSet.AWSLogSystem = LogSet.OldLogger; + LogSet.OldLogger = nullptr; } } // namespace Logging