From 26369a3a010ad4c34b28766318bc1835403c1bf0 Mon Sep 17 00:00:00 2001 From: Yabin Cui Date: Fri, 10 Feb 2017 18:05:34 -0800 Subject: [PATCH] libbacktraceoffline: make it thread-safe. Make libbacktraceoffline thread-safe by protecting the global variable with a lock. So it can be used in a multi-thread environment, like by simpleperf inplace sampling. Bug: http://b/30974760 Test: no Change-Id: I4699bf15dfa69ac75faeb4e79a73fb3af0f08dfc --- libbacktrace/BacktraceOffline.cpp | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/libbacktrace/BacktraceOffline.cpp b/libbacktrace/BacktraceOffline.cpp index 53ea79677..0a2f5a31f 100644 --- a/libbacktrace/BacktraceOffline.cpp +++ b/libbacktrace/BacktraceOffline.cpp @@ -31,6 +31,7 @@ extern "C" { #include #include +#include #include #include @@ -91,9 +92,6 @@ struct DebugFrameInfo { has_debug_frame(false), has_gnu_debugdata(false) { } }; -static std::unordered_map>& g_debug_frames = - *new std::unordered_map>; - void Space::Clear() { start = 0; end = 0; @@ -557,18 +555,31 @@ std::string BacktraceOffline::GetFunctionNameRaw(uintptr_t, uintptr_t* offset) { return ""; } +static std::mutex g_lock; +static std::unordered_map>* g_debug_frames = nullptr; + static DebugFrameInfo* ReadDebugFrameFromFile(const std::string& filename); DebugFrameInfo* BacktraceOffline::GetDebugFrameInFile(const std::string& filename) { if (cache_file_) { - auto it = g_debug_frames.find(filename); - if (it != g_debug_frames.end()) { - return it->second.get(); + std::lock_guard lock(g_lock); + if (g_debug_frames != nullptr) { + auto it = g_debug_frames->find(filename); + if (it != g_debug_frames->end()) { + return it->second.get(); + } } } DebugFrameInfo* debug_frame = ReadDebugFrameFromFile(filename); if (cache_file_) { - g_debug_frames.emplace(filename, std::unique_ptr(debug_frame)); + std::lock_guard lock(g_lock); + if (g_debug_frames == nullptr) { + g_debug_frames = new std::unordered_map>; + } + auto pair = g_debug_frames->emplace(filename, std::unique_ptr(debug_frame)); + if (!pair.second) { + debug_frame = pair.first->second.get(); + } } return debug_frame; }