[Lldb-commits] [lldb] r124850 - in /lldb/branches/apple/calcite/lldb: include/lldb/Core/Broadcaster.h include/lldb/Target/Process.h source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp source/Target/Process.cpp tools/debugserver/source/RNBRemote.cpp

Jim Ingham jingham at apple.com
Thu Feb 3 18:47:53 PST 2011


Author: jingham
Date: Thu Feb  3 20:47:53 2011
New Revision: 124850

URL: http://llvm.org/viewvc/llvm-project?rev=124850&view=rev
Log:
Fix Halt to not Pause the private state thread and then try to read from it.
Rijigger the logic in Process::RunThreadPlan to timeout the "Run All Threads" try as well.
Check Greg's fixes to DoHalt in RNBRemote.

Modified:
    lldb/branches/apple/calcite/lldb/include/lldb/Core/Broadcaster.h
    lldb/branches/apple/calcite/lldb/include/lldb/Target/Process.h
    lldb/branches/apple/calcite/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
    lldb/branches/apple/calcite/lldb/source/Target/Process.cpp
    lldb/branches/apple/calcite/lldb/tools/debugserver/source/RNBRemote.cpp

Modified: lldb/branches/apple/calcite/lldb/include/lldb/Core/Broadcaster.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/apple/calcite/lldb/include/lldb/Core/Broadcaster.h?rev=124850&r1=124849&r2=124850&view=diff
==============================================================================
--- lldb/branches/apple/calcite/lldb/include/lldb/Core/Broadcaster.h (original)
+++ lldb/branches/apple/calcite/lldb/include/lldb/Core/Broadcaster.h Thu Feb  3 20:47:53 2011
@@ -195,9 +195,6 @@
     bool
     RemoveListener (Listener* listener, uint32_t event_mask = UINT32_MAX);
     
-protected:
-
-    
     //------------------------------------------------------------------
     /// Provides a simple mechanism to temporarily redirect events from 
     /// broadcaster.  When you call this function passing in a listener and
@@ -237,6 +234,9 @@
     void
     RestoreBroadcaster ();
 
+protected:
+
+    
     void
     PrivateBroadcastEvent (lldb::EventSP &event_sp, bool unique);
 

Modified: lldb/branches/apple/calcite/lldb/include/lldb/Target/Process.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/apple/calcite/lldb/include/lldb/Target/Process.h?rev=124850&r1=124849&r2=124850&view=diff
==============================================================================
--- lldb/branches/apple/calcite/lldb/include/lldb/Target/Process.h (original)
+++ lldb/branches/apple/calcite/lldb/include/lldb/Target/Process.h Thu Feb  3 20:47:53 2011
@@ -1666,6 +1666,26 @@
     PeekAtStateChangedEvents ();
     
 
+    class
+    ProcessEventHijacker
+    {
+    public:
+        ProcessEventHijacker (Process &process, Listener *listener) :
+            m_process (process),
+            m_listener (listener)
+        {
+            m_process.HijackProcessEvents (listener);
+        }
+        ~ProcessEventHijacker ()
+        {
+            m_process.RestoreProcessEvents();
+        }
+         
+    private:
+        Process &m_process;
+        Listener *m_listener;
+    };
+    friend class ProcessEventHijacker;
     //------------------------------------------------------------------
     /// If you need to ensure that you and only you will hear about some public
     /// event, then make a new listener, set to listen to process events, and
@@ -1882,6 +1902,11 @@
         DISALLOW_COPY_AND_ASSIGN (MemoryCache);
     };
 
+    bool 
+    HijackPrivateProcessEvents (Listener *listener);
+    
+    void 
+    RestorePrivateProcessEvents ();
 
     //------------------------------------------------------------------
     // Member variables

Modified: lldb/branches/apple/calcite/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/apple/calcite/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp?rev=124850&r1=124849&r2=124850&view=diff
==============================================================================
--- lldb/branches/apple/calcite/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp (original)
+++ lldb/branches/apple/calcite/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp Thu Feb  3 20:47:53 2011
@@ -525,30 +525,39 @@
                 timeout = TimeValue::Now();
                 timeout.OffsetWithSeconds (seconds_to_wait_for_stop);
             }
+            ProcessGDBRemoteLog::LogIf (GDBR_LOG_PACKETS | GDBR_LOG_PROCESS, "sending packet: \\x03");
             size_t bytes_written = Write (&ctrl_c, 1, status, NULL);
-            ProcessGDBRemoteLog::LogIf (GDBR_LOG_PACKETS | GDBR_LOG_PROCESS, "send packet: \\x03");
+            ProcessGDBRemoteLog::LogIf (GDBR_LOG_PACKETS | GDBR_LOG_PROCESS, "sent packet: \\x03");
             if (bytes_written > 0)
             {
                 sent_interrupt = true;
                 if (seconds_to_wait_for_stop)
                 {
-                    m_private_is_running.WaitForValueEqualTo (false, &timeout, &timed_out);
-                    if (log)
-                        log->Printf ("GDBRemoteCommunication::%s () - sent interrupt, private state stopped", __FUNCTION__);
-
+                    if (m_private_is_running.WaitForValueEqualTo (false, &timeout, &timed_out))
+                    {
+                        if (log)
+                            log->Printf ("GDBRemoteCommunication::%s () - sent interrupt, private state stopped", __FUNCTION__);
+                        return true;
+                    }
+                    else
+                    {
+                        if (log)
+                            log->Printf ("GDBRemoteCommunication::%s () - sent interrupt, timed out wating for async thread resume", __FUNCTION__);
+                    }
                 }
                 else
                 {
                     if (log)
                         log->Printf ("GDBRemoteCommunication::%s () - sent interrupt, not waiting for stop...", __FUNCTION__);                    
+                    return true;
                 }
-                return true;
             }
             else
             {
                 if (log)
                     log->Printf ("GDBRemoteCommunication::%s () - failed to write interrupt", __FUNCTION__);
             }
+            return false;
         }
         else
         {
@@ -556,7 +565,7 @@
                 log->Printf ("GDBRemoteCommunication::%s () - got sequence mutex without having to interrupt", __FUNCTION__);
         }
     }
-    return false;
+    return true;
 }
 
 bool

Modified: lldb/branches/apple/calcite/lldb/source/Target/Process.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/apple/calcite/lldb/source/Target/Process.cpp?rev=124850&r1=124849&r2=124850&view=diff
==============================================================================
--- lldb/branches/apple/calcite/lldb/source/Target/Process.cpp (original)
+++ lldb/branches/apple/calcite/lldb/source/Target/Process.cpp Thu Feb  3 20:47:53 2011
@@ -393,6 +393,23 @@
     RestoreBroadcaster();
 }
 
+bool
+Process::HijackPrivateProcessEvents (Listener *listener)
+{
+    if (listener != NULL)
+    {
+        return m_private_state_broadcaster.HijackBroadcaster(listener, eBroadcastBitStateChanged);
+    }
+    else
+        return false;
+}
+
+void
+Process::RestorePrivateProcessEvents ()
+{
+    m_private_state_broadcaster.RestoreBroadcaster();
+}
+
 StateType
 Process::WaitForStateChangedEvents (const TimeValue *timeout, EventSP &event_sp)
 {
@@ -1784,7 +1801,8 @@
 {
     // Pause our private state thread so we can ensure no one else eats
     // the stop event out from under us.
-    PausePrivateStateThread();
+    Listener halt_listener ("lldb.process.halt_listener");
+    HijackPrivateProcessEvents(&halt_listener);
 
     EventSP event_sp;
     Error error (WillHalt());
@@ -1813,16 +1831,17 @@
                 // a halt command.
                 if (caused_stop)
                 {
-                    // Wait for 2 seconds for the process to stop.
+                    // Wait for 1 second for the process to stop.
                     TimeValue timeout_time;
                     timeout_time = TimeValue::Now();
                     timeout_time.OffsetWithSeconds(1);
-                    StateType state = WaitForStateChangedEventsPrivate (&timeout_time, event_sp);
+                    bool got_event = halt_listener.WaitForEvent (&timeout_time, event_sp);
+                    StateType state = ProcessEventData::GetStateFromEvent(event_sp.get());
                     
-                    if (state == eStateInvalid)
+                    if (!got_event || state == eStateInvalid)
                     {
                         // We timeout out and didn't get a stop event...
-                        error.SetErrorString ("Halt timed out.");
+                        error.SetErrorStringWithFormat ("Halt timed out. State = %s", StateAsCString(GetState()));
                     }
                     else
                     {
@@ -1847,7 +1866,7 @@
         }
     }
     // Resume our private state thread before we post the event (if any)
-    ResumePrivateStateThread();
+    RestorePrivateProcessEvents();
 
     // Post any event we might have consumed. If all goes well, we will have
     // stopped the process, intercepted the event and set the interrupted
@@ -2684,8 +2703,7 @@
     if (m_private_state.GetValue() != eStateStopped)
     {
         errors.Printf ("RunThreadPlan called while the private state was not stopped.");
-        // REMOVE BEAR TRAP...
-        // abort();
+        return lldb::eExecutionSetupError;
     }
     
     // Save this value for restoration of the execution context after we run
@@ -2711,73 +2729,186 @@
     exe_ctx.thread->QueueThreadPlan(thread_plan_sp, true);
     
     Listener listener("lldb.process.listener.run-thread-plan");
-    exe_ctx.process->HijackProcessEvents(&listener);
+    
+    // This process event hijacker Hijacks the Public events and its destructor makes sure that the process events get 
+    // restored on exit to the function.
+    
+    ProcessEventHijacker run_thread_plan_hijacker (*this, &listener);
         
     lldb::LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_STEP | LIBLLDB_LOG_PROCESS));
     if (log)
     {
         StreamString s;
         thread_plan_sp->GetDescription(&s, lldb::eDescriptionLevelVerbose);
-        log->Printf ("Process::RunThreadPlan(): Resuming thread %u - 0x%4.4x to run thread plan \"%s\".",  exe_ctx.thread->GetIndexID(), exe_ctx.thread->GetID(), s.GetData());
+        log->Printf ("Process::RunThreadPlan(): Resuming thread %u - 0x%4.4x to run thread plan \"%s\".",  
+                     exe_ctx.thread->GetIndexID(), 
+                     exe_ctx.thread->GetID(), 
+                     s.GetData());
     }
     
-    Error resume_error = exe_ctx.process->Resume ();
-    if (!resume_error.Success())
-    {
-        errors.Printf("Error resuming inferior: \"%s\".\n", resume_error.AsCString());
-        exe_ctx.process->RestoreProcessEvents();
-        return lldb::eExecutionSetupError;
-    }
-    
-    // We need to call the function synchronously, so spin waiting for it to return.
-    // If we get interrupted while executing, we're going to lose our context, and
-    // won't be able to gather the result at this point.
-    // We set the timeout AFTER the resume, since the resume takes some time and we
-    // don't want to charge that to the timeout.
+    bool got_event;
+    lldb::EventSP event_sp;
+    lldb::StateType stop_state = lldb::eStateInvalid;
     
     TimeValue* timeout_ptr = NULL;
     TimeValue real_timeout;
     
-    if (single_thread_timeout_usec != 0)
-    {
-        real_timeout = TimeValue::Now();
-        real_timeout.OffsetWithMicroSeconds(single_thread_timeout_usec);
-        timeout_ptr = &real_timeout;
-    }
+    bool first_timeout = true;
+    bool do_resume = true;
     
     while (1)
     {
-        lldb::EventSP event_sp;
-        lldb::StateType stop_state = lldb::eStateInvalid;
+        // We usually want to resume the process if we get to the top of the loop.
+        // The only exception is if we get two running events with no intervening
+        // stop, which can happen, we will just wait for then next stop event.
+        
+        if (do_resume)
+        {
+            // Do the initial resume and wait for the running event before going further.
+    
+            Error resume_error = exe_ctx.process->Resume ();
+            if (!resume_error.Success())
+            {
+                errors.Printf("Error resuming inferior: \"%s\".\n", resume_error.AsCString());
+                return_value = lldb::eExecutionSetupError;
+                break;
+            }
+    
+            real_timeout = TimeValue::Now();
+            real_timeout.OffsetWithMicroSeconds(500000);
+            timeout_ptr = &real_timeout;
+            
+            got_event = listener.WaitForEvent(NULL, event_sp);
+            if (!got_event) 
+            {
+                if (log)
+                    log->Printf("Didn't get any event after initial resume, exiting.");
+
+                errors.Printf("Didn't get any event after initial resume, exiting.");
+                return_value = lldb::eExecutionSetupError;
+                break;
+            }
+            
+            stop_state = Process::ProcessEventData::GetStateFromEvent(event_sp.get());
+            if (stop_state != eStateRunning)
+            {
+                if (log)
+                    log->Printf("Didn't get running event after initial resume, got %s instead.", StateAsCString(stop_state));
+
+                errors.Printf("Didn't get running event after initial resume, got %s instead.", StateAsCString(stop_state));
+                return_value = lldb::eExecutionSetupError;
+                break;
+            }
+        
+            if (log)
+                log->Printf ("Resuming succeeded.");
+            // We need to call the function synchronously, so spin waiting for it to return.
+            // If we get interrupted while executing, we're going to lose our context, and
+            // won't be able to gather the result at this point.
+            // We set the timeout AFTER the resume, since the resume takes some time and we
+            // don't want to charge that to the timeout.
+            
+            if (single_thread_timeout_usec != 0)
+            {
+                real_timeout = TimeValue::Now();
+                real_timeout.OffsetWithMicroSeconds(single_thread_timeout_usec);
+                timeout_ptr = &real_timeout;
+            }
+        }
+        else
+        {
+            if (log)
+                log->Printf ("Handled an extra running event.");
+            do_resume = true;
+        }
+        
         // Now wait for the process to stop again:
-        bool got_event = listener.WaitForEvent (timeout_ptr, event_sp);
+        stop_state = lldb::eStateInvalid;
+        event_sp.reset();
+        got_event = listener.WaitForEvent (timeout_ptr, event_sp);
         
-        if (!got_event)
+        if (got_event)
         {
-            // Right now this is the only way to tell we've timed out...
-            // We should interrupt the process here...
+            if (event_sp.get())
+            {
+                bool keep_going = false;
+                stop_state = Process::ProcessEventData::GetStateFromEvent(event_sp.get());
+                if (log)
+                    log->Printf("In while loop, got event: %s.", StateAsCString(stop_state));
+                    
+                switch (stop_state)
+                {
+                case lldb::eStateStopped:
+                    // Yay, we're done.
+                    if (log)
+                        log->Printf ("Execution completed successfully.");
+                    return_value = lldb::eExecutionCompleted;
+                    break;
+                case lldb::eStateCrashed:
+                    if (log)
+                        log->Printf ("Execution crashed.");
+                    return_value = lldb::eExecutionInterrupted;
+                    break;
+                case lldb::eStateRunning:
+                    do_resume = false;
+                    keep_going = true;
+                    break;
+                default:
+                    if (log)
+                        log->Printf("Execution stopped with unexpected state: %s.", StateAsCString(stop_state));
+                    return_value = lldb::eExecutionInterrupted;
+                    break;
+                }
+                if (keep_going)
+                    continue;
+                else
+                    break;
+            } 
+            else
+            {
+                if (log)
+                    log->Printf ("got_event was true, but the event pointer was null.  How odd...");
+                return_value = lldb::eExecutionInterrupted;
+                break;
+            }
+        }
+        else
+        {
+            // If we didn't get an event that means we've timed out...
+            // We will interrupt the process here.  Depending on what we were asked to do we will
+            // either exit, or try with all threads running for the same timeout.
             // Not really sure what to do if Halt fails here...
+            
             if (log) {
                 if (try_all_threads)
-                    log->Printf ("Process::RunThreadPlan(): Running function with timeout: %d timed out, trying with all threads enabled.",
-                                 single_thread_timeout_usec);
+                {
+                    if (first_timeout)
+                        log->Printf ("Process::RunThreadPlan(): Running function with timeout: %d timed out, "
+                                     "trying with all threads enabled.",
+                                     single_thread_timeout_usec);
+                    else
+                        log->Printf ("Process::RunThreadPlan(): Restarting function with all threads enabled "
+                                     "and timeout: %d timed out.",
+                                     single_thread_timeout_usec);
+                }
                 else
-                    log->Printf ("Process::RunThreadPlan(): Running function with timeout: %d timed out, abandoning execution.", 
+                    log->Printf ("Process::RunThreadPlan(): Running function with timeout: %d timed out, "
+                                 "halt and abandoning execution.", 
                                  single_thread_timeout_usec);
             }
             
             Error halt_error = exe_ctx.process->Halt();
-            
             if (halt_error.Success())
             {
-                timeout_ptr = NULL;
                 if (log)
                     log->Printf ("Process::RunThreadPlan(): Halt succeeded.");
                     
-                // Between the time that we got the timeout and the time we halted, but target
-                // might have actually completed the plan.  If so, we're done.  Note, I call WFE here with a short 
-                // timeout to 
-                got_event = listener.WaitForEvent(NULL, event_sp);
+                // If halt succeeds, it always produces a stopped event.  Wait for that:
+                
+                real_timeout = TimeValue::Now();
+                real_timeout.OffsetWithMicroSeconds(500000);
+
+                got_event = listener.WaitForEvent(&real_timeout, event_sp);
                 
                 if (got_event)
                 {
@@ -2785,184 +2916,253 @@
                     if (log)
                     {
                         log->Printf ("Process::RunThreadPlan(): Stopped with event: %s", StateAsCString(stop_state));
-                        if (stop_state == lldb::eStateStopped && Process::ProcessEventData::GetInterruptedFromEvent(event_sp.get()))
+                        if (stop_state == lldb::eStateStopped 
+                            && Process::ProcessEventData::GetInterruptedFromEvent(event_sp.get()))
                             log->Printf ("    Event was the Halt interruption event.");
                     }
                     
-                    if (exe_ctx.thread->IsThreadPlanDone (thread_plan_sp.get()))
+                    if (stop_state == lldb::eStateStopped)
                     {
-                        if (log)
-                            log->Printf ("Process::RunThreadPlan(): Even though we timed out, the call plan was done.  Exiting wait loop.");
-                        return_value = lldb::eExecutionCompleted;
-                        break;
-                    }
+                        // Between the time we initiated the Halt and the time we delivered it, the process could have
+                        // already finished its job.  Check that here:
+                        
+                        if (exe_ctx.thread->IsThreadPlanDone (thread_plan_sp.get()))
+                        {
+                            if (log)
+                                log->Printf ("Process::RunThreadPlan(): Even though we timed out, the call plan was done.  "
+                                             "Exiting wait loop.");
+                            return_value = lldb::eExecutionCompleted;
+                            break;
+                        }
 
-                    if (try_all_threads 
-                        && (stop_state == lldb::eStateStopped && Process::ProcessEventData::GetInterruptedFromEvent (event_sp.get())))
-                    {
+                        if (!try_all_threads)
+                        {
+                            if (log)
+                                log->Printf ("try_all_threads was false, we stopped so now we're quitting.");
+                            return_value = lldb::eExecutionInterrupted;
+                            break;
+                        }
                         
-                        thread_plan_sp->SetStopOthers (false);
-                        if (log)
-                            log->Printf ("Process::RunThreadPlan(): About to resume.");
+                        if (first_timeout)
+                        {
+                            // Set all the other threads to run, and return to the top of the loop, which will continue;
+                            first_timeout = false;
+                            thread_plan_sp->SetStopOthers (false);
+                            if (log)
+                                log->Printf ("Process::RunThreadPlan(): About to resume.");
 
-                        exe_ctx.process->Resume();
-                        continue;
-                    }
-                    else
-                    {
-                        exe_ctx.process->RestoreProcessEvents ();
-                        return lldb::eExecutionInterrupted;
+                            continue;
+                        }
+                        else
+                        {
+                            // Running all threads failed, so return Interrupted.
+                            if (log)
+                                log->Printf("Process::RunThreadPlan(): running all threads timed out.");
+                            return_value = lldb::eExecutionInterrupted;
+                            break;
+                        }
                     }
                 }
+                else
+                {   if (log)
+                        log->Printf("Process::RunThreadPlan(): halt said it succeeded, but I got no event.  "
+                                "I'm getting out of here passing Interrupted.");
+                    return_value = lldb::eExecutionInterrupted;
+                    break;
+                }
             }
             else
             {
-                
+                // This branch is to work around some problems with gdb-remote's Halt.  It is a little racy, and can return 
+                // an error from halt, but if you wait a bit you'll get a stopped event anyway.
                 if (log)
-                    log->Printf ("Process::RunThreadPlan(): halt failed: error = \"%s\", I'm just going to wait a little longer and see if the world gets nicer to me.", 
-                                 halt_error.AsCString());
-//                abort();
-                
-                if (single_thread_timeout_usec != 0)
+                    log->Printf ("Process::RunThreadPlan(): halt failed: error = \"%s\", I'm just going to wait a little longer and see if I get a stopped event.", 
+                                 halt_error.AsCString());                
+                real_timeout = TimeValue::Now();
+                real_timeout.OffsetWithMicroSeconds(500000);
+                timeout_ptr = &real_timeout;
+                got_event = listener.WaitForEvent(&real_timeout, event_sp);
+                if (!got_event || event_sp.get() == NULL)
                 {
-                    real_timeout = TimeValue::Now();
-                    real_timeout.OffsetWithMicroSeconds(single_thread_timeout_usec);
-                    timeout_ptr = &real_timeout;
+                    // This is not going anywhere, bag out.
+                    if (log)
+                        log->Printf ("Process::RunThreadPlan(): halt failed: and waiting for the stopped event failed.");
+                    return_value = lldb::eExecutionInterrupted;
+                    break;                
+                }
+                else
+                {
+                    stop_state = Process::ProcessEventData::GetStateFromEvent(event_sp.get());
+                    if (log)
+                        log->Printf ("Process::RunThreadPlan(): halt failed: but then I got a stopped event.  Whatever...");
+                    if (stop_state == lldb::eStateStopped)
+                    {
+                        // Between the time we initiated the Halt and the time we delivered it, the process could have
+                        // already finished its job.  Check that here:
+                        
+                        if (exe_ctx.thread->IsThreadPlanDone (thread_plan_sp.get()))
+                        {
+                            if (log)
+                                log->Printf ("Process::RunThreadPlan(): Even though we timed out, the call plan was done.  "
+                                             "Exiting wait loop.");
+                            return_value = lldb::eExecutionCompleted;
+                            break;
+                        }
+
+                        if (first_timeout)
+                        {
+                            // Set all the other threads to run, and return to the top of the loop, which will continue;
+                            first_timeout = false;
+                            thread_plan_sp->SetStopOthers (false);
+                            if (log)
+                                log->Printf ("Process::RunThreadPlan(): About to resume.");
+
+                            continue;
+                        }
+                        else
+                        {
+                            // Running all threads failed, so return Interrupted.
+                            if (log)
+                                log->Printf("Process::RunThreadPlan(): running all threads timed out.");
+                            return_value = lldb::eExecutionInterrupted;
+                            break;
+                        }
+                    }
+                    else
+                    {
+                        log->Printf ("Process::RunThreadPlan(): halt failed, I waited and didn't get"
+                                     " a stopped event, instead got %s.", StateAsCString(stop_state));
+                        return_value = lldb::eExecutionInterrupted;
+                        break;                
+                    }
                 }
-                continue;
             }
 
         }
         
-        stop_state = Process::ProcessEventData::GetStateFromEvent(event_sp.get());
+    }  // END WAIT LOOP
+    
+    // Now do some processing on the results of the run:
+    if (return_value == eExecutionInterrupted)
+    {
         if (log)
-            log->Printf("Process::RunThreadPlan(): got event: %s.", StateAsCString(stop_state));
-        
-        if (stop_state == lldb::eStateRunning || stop_state == lldb::eStateStepping)
-            continue;
-        
-        if (exe_ctx.thread->IsThreadPlanDone (thread_plan_sp.get()))
         {
-            if (log)
-                log->Printf("Process::RunThreadPlan(): thread plan is done");
-            return_value = lldb::eExecutionCompleted;
-            break;
-        }
-        else if (exe_ctx.thread->WasThreadPlanDiscarded (thread_plan_sp.get()))
-        {
-            if (log)
-                log->Printf("Process::RunThreadPlan(): thread plan was discarded");
-            return_value = lldb::eExecutionDiscarded;
-            break;
-        }
-        else
-        {
-            if (log)
+            StreamString s;
+            if (event_sp)
+                event_sp->Dump (&s);
+            else
             {
-                StreamString s;
-                if (event_sp)
-                    event_sp->Dump (&s);
-                else
+                log->Printf ("Process::RunThreadPlan(): Stop event that interrupted us is NULL.");
+            }
+
+            StreamString ts;
+
+            const char *event_explanation;                
+            
+            do 
+            {
+                const Process::ProcessEventData *event_data = Process::ProcessEventData::GetEventDataFromEvent (event_sp.get());
+
+                if (!event_data)
                 {
-                    log->Printf ("Process::RunThreadPlan(): Stop event that interrupted us is NULL.");
+                    event_explanation = "<no event data>";
+                    break;
                 }
+                
+                Process *process = event_data->GetProcessSP().get();
 
-                StreamString ts;
-
-                const char *event_explanation;                
+                if (!process)
+                {
+                    event_explanation = "<no process>";
+                    break;
+                }
                 
-                do 
+                ThreadList &thread_list = process->GetThreadList();
+                
+                uint32_t num_threads = thread_list.GetSize();
+                uint32_t thread_index;
+                
+                ts.Printf("<%u threads> ", num_threads);
+                
+                for (thread_index = 0;
+                     thread_index < num_threads;
+                     ++thread_index)
                 {
-                    const Process::ProcessEventData *event_data = Process::ProcessEventData::GetEventDataFromEvent (event_sp.get());
-
-                    if (!event_data)
-                    {
-                        event_explanation = "<no event data>";
-                        break;
-                    }
+                    Thread *thread = thread_list.GetThreadAtIndex(thread_index).get();
                     
-                    Process *process = event_data->GetProcessSP().get();
-
-                    if (!process)
+                    if (!thread)
                     {
-                        event_explanation = "<no process>";
-                        break;
+                        ts.Printf("<?> ");
+                        continue;
                     }
                     
-                    ThreadList &thread_list = process->GetThreadList();
-                    
-                    uint32_t num_threads = thread_list.GetSize();
-                    uint32_t thread_index;
+                    ts.Printf("<0x%4.4x ", thread->GetID());
+                    RegisterContext *register_context = thread->GetRegisterContext().get();
                     
-                    ts.Printf("<%u threads> ", num_threads);
+                    if (register_context)
+                        ts.Printf("[ip 0x%llx] ", register_context->GetPC());
+                    else
+                        ts.Printf("[ip unknown] ");
                     
-                    for (thread_index = 0;
-                         thread_index < num_threads;
-                         ++thread_index)
+                    lldb::StopInfoSP stop_info_sp = thread->GetStopInfo();
+                    if (stop_info_sp)
                     {
-                        Thread *thread = thread_list.GetThreadAtIndex(thread_index).get();
-                        
-                        if (!thread)
-                        {
-                            ts.Printf("<?> ");
-                            continue;
-                        }
-                        
-                        ts.Printf("<0x%4.4x ", thread->GetID());
-                        RegisterContext *register_context = thread->GetRegisterContext().get();
-                        
-                        if (register_context)
-                            ts.Printf("[ip 0x%llx] ", register_context->GetPC());
-                        else
-                            ts.Printf("[ip unknown] ");
-                        
-                        lldb::StopInfoSP stop_info_sp = thread->GetStopInfo();
-                        if (stop_info_sp)
-                        {
-                            const char *stop_desc = stop_info_sp->GetDescription();
-                            if (stop_desc)
-                                ts.PutCString (stop_desc);
-                        }
-                        ts.Printf(">");
+                        const char *stop_desc = stop_info_sp->GetDescription();
+                        if (stop_desc)
+                            ts.PutCString (stop_desc);
                     }
-                    
-                    event_explanation = ts.GetData();
-                } while (0);
-                
-                // See if any of the threads that stopped think we ought to stop.  Otherwise continue on.
-                if (!GetThreadList().ShouldStop(event_sp.get()))
-                {
-                    if (log)
-                        log->Printf("Process::RunThreadPlan(): execution interrupted, but nobody wanted to stop, so we continued: %s %s", 
-                                    s.GetData(), event_explanation);
-                    if (single_thread_timeout_usec != 0)
-                    {
-                        real_timeout = TimeValue::Now();
-                        real_timeout.OffsetWithMicroSeconds(single_thread_timeout_usec);
-                        timeout_ptr = &real_timeout;
-                    }
-    
-                    continue;
+                    ts.Printf(">");
                 }
-                else
-                {
-                    if (log)
-                        log->Printf("Process::RunThreadPlan(): execution interrupted: %s %s", s.GetData(), event_explanation);
-                }
-            }
+                
+                event_explanation = ts.GetData();
+            } while (0);
             
+            if (log)
+                log->Printf("Process::RunThreadPlan(): execution interrupted: %s %s", s.GetData(), event_explanation);
+                
             if (discard_on_error && thread_plan_sp)
             {
                 exe_ctx.thread->DiscardThreadPlansUpToPlan (thread_plan_sp);
             }
-            return_value = lldb::eExecutionInterrupted;
-            break;
         }
     }
-    
-    if (exe_ctx.process)
-        exe_ctx.process->RestoreProcessEvents ();
+    else if (return_value == eExecutionSetupError)
+    {
+        if (log)
+            log->Printf("Process::RunThreadPlan(): execution set up error.");
             
+        if (discard_on_error && thread_plan_sp)
+        {
+            exe_ctx.thread->DiscardThreadPlansUpToPlan (thread_plan_sp);
+        }
+    }
+    else
+    {
+        if (exe_ctx.thread->IsThreadPlanDone (thread_plan_sp.get()))
+        {
+            if (log)
+                log->Printf("Process::RunThreadPlan(): thread plan is done");
+            return_value = lldb::eExecutionCompleted;
+        }
+        else if (exe_ctx.thread->WasThreadPlanDiscarded (thread_plan_sp.get()))
+        {
+            if (log)
+                log->Printf("Process::RunThreadPlan(): thread plan was discarded");
+            return_value = lldb::eExecutionDiscarded;
+        }
+        else
+        {
+            if (log)
+                log->Printf("Process::RunThreadPlan(): thread plan stopped in mid course");
+            if (discard_on_error && thread_plan_sp)
+            {
+                if (log)
+                    log->Printf("Process::RunThreadPlan(): discarding thread plan 'cause discard_on_error is set.");
+                exe_ctx.thread->DiscardThreadPlansUpToPlan (thread_plan_sp);
+            }
+        }
+    }
+                
     // Thread we ran the function in may have gone away because we ran the target
     // Check that it's still there.
     exe_ctx.thread = exe_ctx.process->GetThreadList().FindThreadByIndexID(tid, true).get();

Modified: lldb/branches/apple/calcite/lldb/tools/debugserver/source/RNBRemote.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/apple/calcite/lldb/tools/debugserver/source/RNBRemote.cpp?rev=124850&r1=124849&r2=124850&view=diff
==============================================================================
--- lldb/branches/apple/calcite/lldb/tools/debugserver/source/RNBRemote.cpp (original)
+++ lldb/branches/apple/calcite/lldb/tools/debugserver/source/RNBRemote.cpp Thu Feb  3 20:47:53 2011
@@ -3134,6 +3134,7 @@
 rnb_err_t
 RNBRemote::HandlePacket_stop_process (const char *p)
 {
+    DNBLogThreadedIf(LOG_PROCESS, "About to send SIGSTOP to process.");
     DNBProcessSignal (m_ctx.ProcessID(), SIGSTOP);
     //DNBProcessSignal (m_ctx.ProcessID(), SIGINT);
     // Do not send any response packet! Wait for the stop reply packet to naturally happen





More information about the lldb-commits mailing list