summaryrefslogtreecommitdiffstats
path: root/lldb/source/Core/Mangled.cpp
diff options
context:
space:
mode:
authorBenjamin Kramer <benny.kra@googlemail.com>2010-06-22 15:28:29 +0000
committerBenjamin Kramer <benny.kra@googlemail.com>2010-06-22 15:28:29 +0000
commit53a61dc531d19ff4576e4933f96da6478d417b36 (patch)
treee3bad5543f1562855ab17d369b0ecad87dd565dd /lldb/source/Core/Mangled.cpp
parent3986af0c5a09d7daa9b4dad537832cc627ef4c2b (diff)
downloadbcm5719-llvm-53a61dc531d19ff4576e4933f96da6478d417b36.tar.gz
bcm5719-llvm-53a61dc531d19ff4576e4933f96da6478d417b36.zip
Ensure GetDemangledName's thread safety by making the demangle buffer thread specific.
I'm not sure when multiple threads enter this method but a race-condition causing a crash in malloc can be reproduced with this little script: echo file $(which lldb) > cmd echo "run\nbreak set -n main\nrun\nexit" >> cmd lldb -s cmd It may need a few runs before it crashes though. llvm-svn: 106544
Diffstat (limited to 'lldb/source/Core/Mangled.cpp')
-rw-r--r--lldb/source/Core/Mangled.cpp66
1 files changed, 54 insertions, 12 deletions
diff --git a/lldb/source/Core/Mangled.cpp b/lldb/source/Core/Mangled.cpp
index 95cbe382892..cb4335bb6aa 100644
--- a/lldb/source/Core/Mangled.cpp
+++ b/lldb/source/Core/Mangled.cpp
@@ -118,6 +118,40 @@ Mangled::SetValue (const char *s, bool mangled)
}
}
+namespace
+{
+ //------------------------------------------------------------------
+ // Convenience wrapper for __cxa_demangle.
+ //------------------------------------------------------------------
+ class DemangleBuffer
+ {
+ char *m_demangle_buf;
+ size_t m_demangle_buf_len;
+ public:
+ DemangleBuffer () : m_demangle_buf (NULL), m_demangle_buf_len (0) {}
+ ~DemangleBuffer ()
+ {
+ free (m_demangle_buf);
+ }
+ int Demangle (const char *mangled)
+ {
+ int status = 0;
+ m_demangle_buf = abi::__cxa_demangle(mangled, m_demangle_buf,
+ &m_demangle_buf_len, &status);
+ return status;
+ }
+ const char *GetBuffer () const { return m_demangle_buf; }
+ size_t GetLength () const { return m_demangle_buf_len; }
+ };
+}
+
+//----------------------------------------------------------------------
+// Used to delete the thread specific buffer when the thread exits.
+//----------------------------------------------------------------------
+static void FreeDemangleBuffer (void *buf)
+{
+ delete static_cast<DemangleBuffer*> (buf);
+}
//----------------------------------------------------------------------
// Generate the demangled name on demand using this accessor. Code in
@@ -147,19 +181,27 @@ Mangled::GetDemangledName () const
// return a buffer value and length and we will continue to
// re-use that buffer so we don't always have to malloc/free
// a buffer for each demangle. The buffer can be realloc'ed
- // by abi::__cxa_demangle, so we may need to make it thread
- // specific if we ever start doing multi-threaded calls to
- // this function. g_demangle_buf will currently leak one
- // malloc entry that can vary in size. If we need to reclaim
- // this memory, we will need to add some code to free this
- // buffer at exit time.
- static char *g_demangle_buf = NULL;
- static size_t g_demangle_buf_len = 0;
- int status = 0;
- g_demangle_buf = abi::__cxa_demangle(mangled, g_demangle_buf, &g_demangle_buf_len, &status);
- if (g_demangle_buf != NULL)
+ // by abi::__cxa_demangle, so we need to make it thread
+ // specific.
+
+ // Set up thread specific storage.
+ static pthread_key_t g_demangle_key = 0;
+ if (!g_demangle_key)
+ ::pthread_key_create (&g_demangle_key, FreeDemangleBuffer);
+
+ DemangleBuffer *buf = static_cast<DemangleBuffer*> (
+ ::pthread_getspecific (g_demangle_key));
+ if (!buf) // No buffer for this thread, create a new one.
+ {
+ buf = new DemangleBuffer ();
+ ::pthread_setspecific (g_demangle_key, buf);
+ }
+
+ int status = buf->Demangle (mangled);
+ if (status == 0)
{
- m_demangled.SetCString(g_demangle_buf);
+ m_demangled.SetCStringWithLength(buf->GetBuffer(),
+ buf->GetLength());
}
else
{
OpenPOWER on IntegriCloud