[Lldb-commits] [lldb] r167197 - in /lldb/trunk/source/Plugins/Process/gdb-remote: ProcessGDBRemote.cpp ProcessGDBRemote.h

Jim Ingham jingham at apple.com
Wed Oct 31 18:15:33 PDT 2012


Author: jingham
Date: Wed Oct 31 20:15:33 2012
New Revision: 167197

URL: http://llvm.org/viewvc/llvm-project?rev=167197&view=rev
Log:
There seems to be some odd corner case where we shut down the ProcessGDBRemote, but we haven't managed to shut down the async thread.  That causes the ProcessGDBRemote::AsyncThread to crash when it wakes up.  So I changed StartAsyncThread and StopAsyncThread to be callable multiple times (only the first one does anything) so that we can just shut it down unequivocally in the ProcessGDBRemote destructor.

<rdar://problem/12602981>

Modified:
    lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
    lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h

Modified: lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp?rev=167197&r1=167196&r2=167197&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp (original)
+++ lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp Wed Oct 31 20:15:33 2012
@@ -188,6 +188,8 @@
     m_register_info (),
     m_async_broadcaster (NULL, "lldb.process.gdb-remote.async-broadcaster"),
     m_async_thread (LLDB_INVALID_HOST_THREAD),
+    m_async_thread_state(eAsyncThreadNotStarted),
+    m_async_thread_state_mutex(Mutex::eMutexTypeRecursive),
     m_thread_ids (),
     m_continue_c_tids (),
     m_continue_C_tids (),
@@ -220,6 +222,12 @@
     // destruct this class, then Process::~Process() might have problems
     // trying to fully destroy the broadcaster.
     Finalize();
+    
+    // The general Finalize is going to try to destroy the process and that SHOULD
+    // shut down the async thread.  However, if we don't kill it it will get stranded and
+    // its connection will go away so when it wakes up it will crash.  So kill it for sure here.
+    StopAsyncThread();
+    KillDebugserverProcess();
 }
 
 //----------------------------------------------------------------------
@@ -2713,11 +2721,32 @@
 
     if (log)
         log->Printf ("ProcessGDBRemote::%s ()", __FUNCTION__);
-
-    // Create a thread that watches our internal state and controls which
-    // events make it to clients (into the DCProcess event queue).
-    m_async_thread = Host::ThreadCreate ("<lldb.process.gdb-remote.async>", ProcessGDBRemote::AsyncThread, this, NULL);
-    return IS_VALID_LLDB_HOST_THREAD(m_async_thread);
+    
+    Mutex::Locker start_locker(m_async_thread_state_mutex);
+    if (m_async_thread_state == eAsyncThreadNotStarted)
+    {
+        // Create a thread that watches our internal state and controls which
+        // events make it to clients (into the DCProcess event queue).
+        m_async_thread = Host::ThreadCreate ("<lldb.process.gdb-remote.async>", ProcessGDBRemote::AsyncThread, this, NULL);
+        if (IS_VALID_LLDB_HOST_THREAD(m_async_thread))
+        {
+            m_async_thread_state = eAsyncThreadRunning;
+            return true;
+        }
+        else
+            return false;
+    }
+    else
+    {
+        // Somebody tried to start the async thread while it was either being started or stopped.  If the former, and
+        // it started up successfully, then say all's well.  Otherwise it is an error, since we aren't going to restart it.
+        if (log)
+            log->Printf ("ProcessGDBRemote::%s () - Called when Async thread was in state: %d.", __FUNCTION__, m_async_thread_state);
+        if (m_async_thread_state == eAsyncThreadRunning)
+            return true;
+        else
+            return false;
+    }
 }
 
 void
@@ -2728,15 +2757,25 @@
     if (log)
         log->Printf ("ProcessGDBRemote::%s ()", __FUNCTION__);
 
-    m_async_broadcaster.BroadcastEvent (eBroadcastBitAsyncThreadShouldExit);
-    
-    //  This will shut down the async thread.
-    m_gdb_comm.Disconnect();    // Disconnect from the debug server.
+    Mutex::Locker start_locker(m_async_thread_state_mutex);
+    if (m_async_thread_state == eAsyncThreadRunning)
+    {
+        m_async_broadcaster.BroadcastEvent (eBroadcastBitAsyncThreadShouldExit);
+        
+        //  This will shut down the async thread.
+        m_gdb_comm.Disconnect();    // Disconnect from the debug server.
 
-    // Stop the stdio thread
-    if (IS_VALID_LLDB_HOST_THREAD(m_async_thread))
+        // Stop the stdio thread
+        if (IS_VALID_LLDB_HOST_THREAD(m_async_thread))
+        {
+            Host::ThreadJoin (m_async_thread, NULL, NULL);
+        }
+        m_async_thread_state = eAsyncThreadDone;
+    }
+    else
     {
-        Host::ThreadJoin (m_async_thread, NULL, NULL);
+        if (log)
+            log->Printf ("ProcessGDBRemote::%s () - Called when Async thread was in state: %d.", __FUNCTION__, m_async_thread_state);
     }
 }
 

Modified: lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h?rev=167197&r1=167196&r2=167197&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h (original)
+++ lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h Wed Oct 31 20:15:33 2012
@@ -307,6 +307,13 @@
         eBroadcastBitAsyncThreadDidExit             = (1 << 2)
     };
 
+    typedef enum AsyncThreadState
+    {
+        eAsyncThreadNotStarted,
+        eAsyncThreadRunning,
+        eAsyncThreadDone
+    } AsyncThreadState;
+    
     lldb_private::Flags m_flags;            // Process specific flags (see eFlags enums)
     GDBRemoteCommunicationClient m_gdb_comm;
     lldb::pid_t m_debugserver_pid;
@@ -315,6 +322,8 @@
     GDBRemoteDynamicRegisterInfo m_register_info;
     lldb_private::Broadcaster m_async_broadcaster;
     lldb::thread_t m_async_thread;
+    AsyncThreadState m_async_thread_state;
+    lldb_private::Mutex m_async_thread_state_mutex;
     typedef std::vector<lldb::tid_t> tid_collection;
     typedef std::vector< std::pair<lldb::tid_t,int> > tid_sig_collection;
     typedef std::map<lldb::addr_t, lldb::addr_t> MMapMap;





More information about the lldb-commits mailing list