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

Jim Ingham jingham at apple.com
Thu Apr 12 11:49:31 PDT 2012


Author: jingham
Date: Thu Apr 12 13:49:31 2012
New Revision: 154601

URL: http://llvm.org/viewvc/llvm-project?rev=154601&view=rev
Log:
Make sure that DoResume doesn't stall if we shut down the async thread while DoResume is waiting
for packet confirmation.  
Also added a bit more logging.
Also, unlock the writer end of the run lock in Process.cpp on our way out of the private state
thread so that the Process can shut down cleanly.

<rdar://problem/11228538>

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

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=154601&r1=154600&r2=154601&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp (original)
+++ lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp Thu Apr 12 13:49:31 2012
@@ -175,6 +175,7 @@
 {
     m_async_broadcaster.SetEventName (eBroadcastBitAsyncThreadShouldExit,   "async thread should exit");
     m_async_broadcaster.SetEventName (eBroadcastBitAsyncContinue,           "async thread continue");
+    m_async_broadcaster.SetEventName (eBroadcastBitAsyncThreadDidExit,      "async thread did exit");
 }
 
 //----------------------------------------------------------------------
@@ -927,6 +928,8 @@
     Listener listener ("gdb-remote.resume-packet-sent");
     if (listener.StartListeningForEvents (&m_gdb_comm, GDBRemoteCommunication::eBroadcastBitRunPacketSent))
     {
+        listener.StartListeningForEvents (&m_async_broadcaster, ProcessGDBRemote::eBroadcastBitAsyncThreadDidExit);
+        
         StreamString continue_packet;
         bool continue_packet_error = false;
         if (m_gdb_comm.HasAnyVContSupport ())
@@ -1122,10 +1125,29 @@
             TimeValue timeout;
             timeout = TimeValue::Now();
             timeout.OffsetWithSeconds (5);
+            if (!IS_VALID_LLDB_HOST_THREAD(m_async_thread))
+            {
+                error.SetErrorString ("Trying to resume but the async thread is dead.");
+                if (log)
+                    log->Printf ("ProcessGDBRemote::DoResume: Trying to resume but the async thread is dead.");
+                return error;
+            }
+            
             m_async_broadcaster.BroadcastEvent (eBroadcastBitAsyncContinue, new EventDataBytes (continue_packet.GetData(), continue_packet.GetSize()));
 
             if (listener.WaitForEvent (&timeout, event_sp) == false)
+            {
                 error.SetErrorString("Resume timed out.");
+                if (log)
+                    log->Printf ("ProcessGDBRemote::DoResume: Resume timed out.");
+            }
+            else if (event_sp->BroadcasterIs (&m_async_broadcaster))
+            {
+                error.SetErrorString ("Broadcast continue, but the async thread was killed before we got an ack back.");
+                if (log)
+                    log->Printf ("ProcessGDBRemote::DoResume: Broadcast continue, but the async thread was killed before we got an ack back.");
+                return error;
+            }
         }
     }
 

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=154601&r1=154600&r2=154601&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h (original)
+++ lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h Thu Apr 12 13:49:31 2012
@@ -293,7 +293,8 @@
     enum
     {
         eBroadcastBitAsyncContinue                  = (1 << 0),
-        eBroadcastBitAsyncThreadShouldExit          = (1 << 1)
+        eBroadcastBitAsyncThreadShouldExit          = (1 << 1),
+        eBroadcastBitAsyncThreadDidExit             = (1 << 2)
     };
 
     lldb_private::Flags m_flags;            // Process specific flags (see eFlags enums)

Modified: lldb/trunk/source/Target/Process.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/Process.cpp?rev=154601&r1=154600&r2=154601&view=diff
==============================================================================
--- lldb/trunk/source/Target/Process.cpp (original)
+++ lldb/trunk/source/Target/Process.cpp Thu Apr 12 13:49:31 2012
@@ -2465,8 +2465,7 @@
         case eStateCrashed:
             {
                 // During attach, prior to sending the eStateStopped event, 
-                // lldb_private::Process subclasses must set the process must set
-                // the new process ID.
+                // lldb_private::Process subclasses must set the new process ID.
                 assert (m_process->GetID() != LLDB_INVALID_PROCESS_ID);
                 if (m_exec_count > 0)
                 {
@@ -2943,6 +2942,11 @@
             m_target.GetDebugger().PopInputReader (m_process_input_reader);
         if (m_process_input_reader)
             m_process_input_reader.reset();
+            
+        // If we have been interrupted (to kill us) in the middle of running, we may not end up propagating
+        // the last events through the event system, in which case we might strand the write lock.  Unlock
+        // it here so when we do to tear down the process we don't get an error destroying the lock.
+        m_run_lock.WriteUnlock();
     }
     return error;
 }
@@ -3133,12 +3137,18 @@
 {
     if (PrivateStateThreadIsValid ())
         ControlPrivateStateThread (eBroadcastInternalStateControlStop);
+    else
+    {
+        LogSP log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
+        if (log)
+            printf ("Went to stop the private state thread, but it was already invalid.");
+    }
 }
 
 void
 Process::ControlPrivateStateThread (uint32_t signal)
 {
-    LogSP log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EVENTS));
+    LogSP log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
 
     assert (signal == eBroadcastInternalStateControlStop ||
             signal == eBroadcastInternalStateControlPause ||
@@ -3160,19 +3170,36 @@
 
         timeout_time = TimeValue::Now();
         timeout_time.OffsetWithSeconds(2);
+        if (log)
+            log->Printf ("Sending control event of type: %d.", signal);
         m_private_state_control_wait.WaitForValueEqualTo (true, &timeout_time, &timed_out);
         m_private_state_control_wait.SetValue (false, eBroadcastNever);
 
         if (signal == eBroadcastInternalStateControlStop)
         {
             if (timed_out)
-                Host::ThreadCancel (private_state_thread, NULL);
+            {
+                Error error;
+                Host::ThreadCancel (private_state_thread, &error);
+                if (log)
+                    log->Printf ("Timed out responding to the control event, cancel got error: \"%s\".", error.AsCString());
+            }
+            else
+            {
+                if (log)
+                    log->Printf ("The control event killed the private state thread without having to cancel.");
+            }
 
             thread_result_t result = NULL;
             Host::ThreadJoin (private_state_thread, &result, NULL);
             m_private_state_thread = LLDB_INVALID_HOST_THREAD;
         }
     }
+    else
+    {
+        if (log)
+            log->Printf ("Private state thread already dead, no need to signal it to stop.");
+    }
 }
 
 void
@@ -3258,7 +3285,7 @@
 Process::RunPrivateStateThread ()
 {
     bool control_only = true;
-    m_private_state_control_wait.SetValue (true, eBroadcastNever);
+    m_private_state_control_wait.SetValue (false, eBroadcastNever);
 
     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
     if (log)
@@ -3271,11 +3298,13 @@
         WaitForEventsPrivate (NULL, event_sp, control_only);
         if (event_sp->BroadcasterIs(&m_private_state_control_broadcaster))
         {
+            if (log)
+                log->Printf ("Process::%s (arg = %p, pid = %llu) got a control event: %d", __FUNCTION__, this, GetID(), event_sp->GetType());
+
             switch (event_sp->GetType())
             {
             case eBroadcastInternalStateControlStop:
                 exit_now = true;
-                continue;   // Go to next loop iteration so we exit without
                 break;      // doing any internal state managment below
 
             case eBroadcastInternalStateControlPause:
@@ -3287,9 +3316,6 @@
                 break;
             }
             
-            if (log)
-                log->Printf ("Process::%s (arg = %p, pid = %llu) got a control event: %d", __FUNCTION__, this, GetID(), event_sp->GetType());
-
             m_private_state_control_wait.SetValue (true, eBroadcastAlways);
             continue;
         }





More information about the lldb-commits mailing list