[Lldb-commits] [lldb] r106544 - /lldb/trunk/source/Core/Mangled.cpp
Benjamin Kramer
benny.kra at googlemail.com
Tue Jun 22 08:28:29 PDT 2010
Author: d0k
Date: Tue Jun 22 10:28:29 2010
New Revision: 106544
URL: http://llvm.org/viewvc/llvm-project?rev=106544&view=rev
Log:
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.
Modified:
lldb/trunk/source/Core/Mangled.cpp
Modified: lldb/trunk/source/Core/Mangled.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/Mangled.cpp?rev=106544&r1=106543&r2=106544&view=diff
==============================================================================
--- lldb/trunk/source/Core/Mangled.cpp (original)
+++ lldb/trunk/source/Core/Mangled.cpp Tue Jun 22 10:28:29 2010
@@ -118,6 +118,40 @@
}
}
+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 @@
// 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
{
More information about the lldb-commits
mailing list