[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