From 4f8e04d3918ba59828df6b915cd4a2cb24da9fc8 Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Sat, 21 Oct 2017 22:37:51 -0300 Subject: [PATCH] Fix a crash on quit if a deprecated function was used. --HG-- branch : minor --- src/common/deprecation.cpp | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/src/common/deprecation.cpp b/src/common/deprecation.cpp index 2733972d9..e04ae93fd 100644 --- a/src/common/deprecation.cpp +++ b/src/common/deprecation.cpp @@ -28,8 +28,8 @@ namespace love { -static std::map deprecated; -static std::vector deprecatedList; +static std::map *deprecated = nullptr; +static std::vector *deprecatedList = nullptr; static std::atomic initCount; @@ -39,17 +39,28 @@ static bool outputEnabled = false; void initDeprecation() { if (initCount.fetch_add(1) == 0) + { mutex = thread::newMutex(); + + // These are heap-allocated because we want to clear them on deinit, + // and deinit may be called when the program is shutting down in the + // middle of static variable cleanup (eg in the Math module destructor). + // Calling std::map::clear() in that case was causing segfaults. + deprecated = new std::map(); + deprecatedList = new std::vector(); + } } void deinitDeprecation() { if (initCount.fetch_sub(1) == 1) { - deprecatedList.clear(); - deprecated.clear(); - + delete deprecated; + delete deprecatedList; delete mutex; + + deprecated = nullptr; + deprecatedList = nullptr; mutex = nullptr; } } @@ -115,7 +126,7 @@ std::string getDeprecationNotice(const DeprecationInfo &info, bool usewhere) } GetDeprecated::GetDeprecated() - : all(deprecatedList) + : all(*deprecatedList) { if (mutex != nullptr) mutex->lock(); @@ -138,9 +149,9 @@ MarkDeprecated::MarkDeprecated(const char *name, APIType api, DeprecationType ty if (mutex != nullptr) mutex->lock(); - auto it = deprecated.find(name); + auto it = deprecated->find(name); - if (it != deprecated.end()) + if (it != deprecated->end()) { it->second.uses++; info = &it->second; @@ -157,10 +168,10 @@ MarkDeprecated::MarkDeprecated(const char *name, APIType api, DeprecationType ty if (replacement != nullptr) newinfo.replacement = replacement; - auto inserted = deprecated.insert(std::make_pair(newinfo.name, newinfo)); + auto inserted = deprecated->insert(std::make_pair(newinfo.name, newinfo)); info = &inserted.first->second; - deprecatedList.push_back(info); + deprecatedList->push_back(info); } }