Added an "Interrupted" bit to the ProcessEventData.  Halt now generates an event
with the Interrupted bit set.  Process::HandlePrivateEvent ignores Interrupted events.
DoHalt is changed to ensure that the stop even is processed, and an event with
the Interrupted event is posted.  Finally ClangFunction is rationalized to use this
facility so the that Halt is handled more deterministically.



git-svn-id: https://llvm.org/svn/llvm-project/llvdb/trunk@119453 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
index 50a7aec..ee03424 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
@@ -199,14 +199,14 @@
         log->Printf ("GDBRemoteCommunication::%s ()", __FUNCTION__);
 
     Mutex::Locker locker(m_sequence_mutex);
-    m_is_running.SetValue (true, eBroadcastNever);
-
 //    ScopedValueChanger<bool> restore_running_to_false (m_is_running, false);
     StateType state = eStateRunning;
 
     if (SendPacket(payload, packet_length) == 0)
         state = eStateInvalid;
 
+    m_is_running.SetValue (true, eBroadcastAlways);
+
     while (state == eStateRunning)
     {
         log = ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS);
@@ -856,3 +856,19 @@
     }
     return false;
 }
+
+bool
+GDBRemoteCommunication::WaitForIsRunning (uint32_t timeout_sec)
+{
+    TimeValue timeout;
+    if (timeout_sec)
+    {
+        timeout = TimeValue::Now();
+        timeout.OffsetWithSeconds (timeout_sec);
+    }
+    bool timed_out = false;
+    m_is_running.WaitForValueEqualTo (true, &timeout, &timed_out);
+    return timed_out;
+}
+    
+
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h
index e556072..ac49bf2 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h
@@ -203,6 +203,9 @@
     }
     
     bool
+    WaitForIsRunning (uint32_t timeout_sec);
+    
+    bool
     GetHostInfo (uint32_t timeout_seconds);
 
     bool 
diff --git a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
index 52499ba..fcbd523 100644
--- a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
+++ b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
@@ -895,9 +895,15 @@
 Error
 ProcessGDBRemote::DoResume ()
 {
+    Error error;
     ProcessGDBRemoteLog::LogIf (GDBR_LOG_PROCESS, "ProcessGDBRemote::Resume()");
     m_async_broadcaster.BroadcastEvent (eBroadcastBitAsyncContinue, new EventDataBytes (m_continue_packet.GetData(), m_continue_packet.GetSize()));
-    return Error();
+    const uint32_t timedout_sec = 1;
+    if (m_gdb_comm.WaitForIsRunning (timedout_sec))
+    {
+        error.SetErrorString("Resume timed out.");
+    }
+    return error;
 }
 
 size_t
@@ -1115,20 +1121,47 @@
 }
 
 Error
-ProcessGDBRemote::DoHalt ()
+ProcessGDBRemote::DoHalt (bool &caused_stop)
 {
     Error error;
+    caused_stop = false;
+    
     if (m_gdb_comm.IsRunning())
     {
+        PausePrivateStateThread();
         bool timed_out = false;
         Mutex::Locker locker;
-        if (!m_gdb_comm.SendInterrupt (locker, 2, &timed_out))
+
+        if (m_gdb_comm.SendInterrupt (locker, 2, &timed_out))
+        {
+            EventSP event_sp;
+            TimeValue timeout_time;
+            timeout_time = TimeValue::Now();
+            timeout_time.OffsetWithSeconds(2);
+
+            StateType state = WaitForStateChangedEventsPrivate (&timeout_time, event_sp);
+
+            if (!StateIsStoppedState (state))
+            {
+                LogSP log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
+                if (log)
+                    log->Printf("ProcessGDBRemote::DoHalt() failed to stop after sending interrupt");
+                error.SetErrorString ("Did not get stopped event after interrupt succeeded.");
+            }
+            else
+                caused_stop = true;
+        }
+        else
         {
             if (timed_out)
                 error.SetErrorString("timed out sending interrupt packet");
             else
                 error.SetErrorString("unknown error sending interrupt packet");
         }
+        
+        // Resume the private state thread at this point.
+        ResumePrivateStateThread();
+
     }
     return error;
 }
@@ -2082,6 +2115,9 @@
             if (listener.WaitForEvent (NULL, event_sp))
             {
                 const uint32_t event_type = event_sp->GetType();
+                if (log)
+                    log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %i) Got an event of type: %d...", __FUNCTION__, arg, process->GetID(), event_type);
+
                 switch (event_type)
                 {
                     case eBroadcastBitAsyncContinue:
diff --git a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
index ae79c5a..1e85e99 100644
--- a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
+++ b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
@@ -138,7 +138,7 @@
     DoResume ();
 
     virtual lldb_private::Error
-    DoHalt ();
+    DoHalt (bool &caused_stop);
 
     virtual lldb_private::Error
     WillDetach ();