[Lldb-commits] [lldb] r160077 - /lldb/trunk/source/Target/Process.cpp

Sean Callanan scallanan at apple.com
Wed Jul 11 14:31:24 PDT 2012


Author: spyffe
Date: Wed Jul 11 16:31:24 2012
New Revision: 160077

URL: http://llvm.org/viewvc/llvm-project?rev=160077&view=rev
Log:
Fixed a bug that caused the Process not to rebroadcast
the fact that a process exited while running a thread
plan.  For example, if a user types the expression

expr (void)exit(0)

then the process terminates but LLDB does not notify
listeners like Xcode that this occurred.

<rdar://problem/11845155>

Modified:
    lldb/trunk/source/Target/Process.cpp

Modified: lldb/trunk/source/Target/Process.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/Process.cpp?rev=160077&r1=160076&r2=160077&view=diff
==============================================================================
--- lldb/trunk/source/Target/Process.cpp (original)
+++ lldb/trunk/source/Target/Process.cpp Wed Jul 11 16:31:24 2012
@@ -4143,546 +4143,565 @@
     
     Listener listener("lldb.process.listener.run-thread-plan");
     
-    // This process event hijacker Hijacks the Public events and its destructor makes sure that the process events get 
-    // restored on exit to the function.
+    lldb::EventSP event_to_broadcast_sp;
     
-    ProcessEventHijacker run_thread_plan_hijacker (*this, &listener);
-        
-    if (log)
     {
-        StreamString s;
-        thread_plan_sp->GetDescription(&s, lldb::eDescriptionLevelVerbose);
-        log->Printf ("Process::RunThreadPlan(): Resuming thread %u - 0x%4.4llx to run thread plan \"%s\".",  
-                     thread->GetIndexID(), 
-                     thread->GetID(), 
-                     s.GetData());
-    }
-    
-    bool got_event;
-    lldb::EventSP event_sp;
-    lldb::StateType stop_state = lldb::eStateInvalid;
-    
-    TimeValue* timeout_ptr = NULL;
-    TimeValue real_timeout;
-    
-    bool first_timeout = true;
-    bool do_resume = true;
-    
-    while (1)
-    {
-        // 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.
+        // This process event hijacker Hijacks the Public events and its destructor makes sure that the process events get
+        // restored on exit to the function.
+        //
+        // If the event needs to propagate beyond the hijacker (e.g., the process exits during execution), then the event
+        // is put into event_to_broadcast_sp for rebroadcasting.
         
-        if (do_resume)
+        ProcessEventHijacker run_thread_plan_hijacker (*this, &listener);
+            
+        if (log)
         {
-            // Do the initial resume and wait for the running event before going further.
-    
-            Error resume_error = PrivateResume ();
-            if (!resume_error.Success())
-            {
-                errors.Printf("Error resuming inferior: \"%s\".\n", resume_error.AsCString());
-                return_value = eExecutionSetupError;
-                break;
-            }
-    
-            real_timeout = TimeValue::Now();
-            real_timeout.OffsetWithMicroSeconds(500000);
-            timeout_ptr = &real_timeout;
+            StreamString s;
+            thread_plan_sp->GetDescription(&s, lldb::eDescriptionLevelVerbose);
+            log->Printf ("Process::RunThreadPlan(): Resuming thread %u - 0x%4.4llx to run thread plan \"%s\".",  
+                         thread->GetIndexID(), 
+                         thread->GetID(), 
+                         s.GetData());
+        }
+        
+        bool got_event;
+        lldb::EventSP event_sp;
+        lldb::StateType stop_state = lldb::eStateInvalid;
+        
+        TimeValue* timeout_ptr = NULL;
+        TimeValue real_timeout;
+        
+        bool first_timeout = true;
+        bool do_resume = true;
+        
+        while (1)
+        {
+            // 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.
             
-            got_event = listener.WaitForEvent(timeout_ptr, event_sp);
-            if (!got_event)
+            if (do_resume)
             {
-                if (log)
-                    log->PutCString("Process::RunThreadPlan(): didn't get any event after initial resume, exiting.");
+                // Do the initial resume and wait for the running event before going further.
+        
+                Error resume_error = PrivateResume ();
+                if (!resume_error.Success())
+                {
+                    errors.Printf("Error resuming inferior: \"%s\".\n", resume_error.AsCString());
+                    return_value = eExecutionSetupError;
+                    break;
+                }
+        
+                real_timeout = TimeValue::Now();
+                real_timeout.OffsetWithMicroSeconds(500000);
+                timeout_ptr = &real_timeout;
+                
+                got_event = listener.WaitForEvent(timeout_ptr, event_sp);
+                if (!got_event)
+                {
+                    if (log)
+                        log->PutCString("Process::RunThreadPlan(): didn't get any event after initial resume, exiting.");
 
-                errors.Printf("Didn't get any event after initial resume, exiting.");
-                return_value = eExecutionSetupError;
-                break;
-            }
+                    errors.Printf("Didn't get any event after initial resume, exiting.");
+                    return_value = eExecutionSetupError;
+                    break;
+                }
+                
+                stop_state = Process::ProcessEventData::GetStateFromEvent(event_sp.get());
+                if (stop_state != eStateRunning)
+                {
+                    if (log)
+                        log->Printf("Process::RunThreadPlan(): 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 = eExecutionSetupError;
+                    break;
+                }
             
-            stop_state = Process::ProcessEventData::GetStateFromEvent(event_sp.get());
-            if (stop_state != eStateRunning)
-            {
                 if (log)
-                    log->Printf("Process::RunThreadPlan(): 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 = eExecutionSetupError;
-                break;
+                    log->PutCString ("Process::RunThreadPlan(): 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;
+                }
             }
-        
-            if (log)
-                log->PutCString ("Process::RunThreadPlan(): 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)
+            else
             {
-                real_timeout = TimeValue::Now();
-                real_timeout.OffsetWithMicroSeconds(single_thread_timeout_usec);
-                    
-                timeout_ptr = &real_timeout;
+                if (log)
+                    log->PutCString ("Process::RunThreadPlan(): handled an extra running event.");
+                do_resume = true;
             }
-        }
-        else
-        {
-            if (log)
-                log->PutCString ("Process::RunThreadPlan(): handled an extra running event.");
-            do_resume = true;
-        }
-        
-        // Now wait for the process to stop again:
-        stop_state = lldb::eStateInvalid;
-        event_sp.reset();
+            
+            // Now wait for the process to stop again:
+            stop_state = lldb::eStateInvalid;
+            event_sp.reset();
 
-        if (log)
-        {
-            if (timeout_ptr)
-            {
-                StreamString s;
-                s.Printf ("about to wait - timeout is:\n   ");
-                timeout_ptr->Dump (&s, 120);
-                s.Printf ("\nNow is:\n    ");
-                TimeValue::Now().Dump (&s, 120);
-                log->Printf ("Process::RunThreadPlan(): %s", s.GetData());
-            }
-            else
+            if (log)
             {
-                log->Printf ("Process::RunThreadPlan(): about to wait forever.");
+                if (timeout_ptr)
+                {
+                    StreamString s;
+                    s.Printf ("about to wait - timeout is:\n   ");
+                    timeout_ptr->Dump (&s, 120);
+                    s.Printf ("\nNow is:\n    ");
+                    TimeValue::Now().Dump (&s, 120);
+                    log->Printf ("Process::RunThreadPlan(): %s", s.GetData());
+                }
+                else
+                {
+                    log->Printf ("Process::RunThreadPlan(): about to wait forever.");
+                }
             }
-        }
-        
-        got_event = listener.WaitForEvent (timeout_ptr, event_sp);
-        
-        if (got_event)
-        {
-            if (event_sp.get())
+            
+            got_event = listener.WaitForEvent (timeout_ptr, event_sp);
+            
+            if (got_event)
             {
-                bool keep_going = false;
-                stop_state = Process::ProcessEventData::GetStateFromEvent(event_sp.get());
-                if (log)
-                    log->Printf("Process::RunThreadPlan(): in while loop, got event: %s.", StateAsCString(stop_state));
-                    
-                switch (stop_state)
+                if (event_sp.get())
                 {
-                case lldb::eStateStopped:
+                    bool keep_going = false;
+                    stop_state = Process::ProcessEventData::GetStateFromEvent(event_sp.get());
+                    if (log)
+                        log->Printf("Process::RunThreadPlan(): in while loop, got event: %s.", StateAsCString(stop_state));
+                        
+                    switch (stop_state)
                     {
-                        // Yay, we're done.  Now make sure that our thread plan actually completed.
-                        ThreadSP thread_sp = GetThreadList().FindThreadByIndexID (thread_idx_id);
-                        if (!thread_sp)
+                    case lldb::eStateStopped:
                         {
-                            // Ooh, our thread has vanished.  Unlikely that this was successful execution...
-                            if (log)
-                                log->Printf ("Process::RunThreadPlan(): execution completed but our thread (index-id=%u) has vanished.", thread_idx_id);
-                            return_value = eExecutionInterrupted;
-                        }
-                        else
-                        {
-                            StopInfoSP stop_info_sp (thread_sp->GetStopInfo ());
-                            StopReason stop_reason = eStopReasonInvalid;
-                            if (stop_info_sp)
-                                 stop_reason = stop_info_sp->GetStopReason();
-                            if (stop_reason == eStopReasonPlanComplete)
+                            // Yay, we're done.  Now make sure that our thread plan actually completed.
+                            ThreadSP thread_sp = GetThreadList().FindThreadByIndexID (thread_idx_id);
+                            if (!thread_sp)
                             {
+                                // Ooh, our thread has vanished.  Unlikely that this was successful execution...
                                 if (log)
-                                    log->PutCString ("Process::RunThreadPlan(): execution completed successfully.");
-                                // Now mark this plan as private so it doesn't get reported as the stop reason
-                                // after this point.  
-                                if (thread_plan_sp)
-                                    thread_plan_sp->SetPrivate (orig_plan_private);
-                                return_value = eExecutionCompleted;
+                                    log->Printf ("Process::RunThreadPlan(): execution completed but our thread (index-id=%u) has vanished.", thread_idx_id);
+                                return_value = eExecutionInterrupted;
                             }
                             else
                             {
-                                if (log)
-                                    log->PutCString ("Process::RunThreadPlan(): thread plan didn't successfully complete.");
+                                StopInfoSP stop_info_sp (thread_sp->GetStopInfo ());
+                                StopReason stop_reason = eStopReasonInvalid;
+                                if (stop_info_sp)
+                                     stop_reason = stop_info_sp->GetStopReason();
+                                if (stop_reason == eStopReasonPlanComplete)
+                                {
+                                    if (log)
+                                        log->PutCString ("Process::RunThreadPlan(): execution completed successfully.");
+                                    // Now mark this plan as private so it doesn't get reported as the stop reason
+                                    // after this point.  
+                                    if (thread_plan_sp)
+                                        thread_plan_sp->SetPrivate (orig_plan_private);
+                                    return_value = eExecutionCompleted;
+                                }
+                                else
+                                {
+                                    if (log)
+                                        log->PutCString ("Process::RunThreadPlan(): thread plan didn't successfully complete.");
 
-                                return_value = eExecutionInterrupted;
+                                    return_value = eExecutionInterrupted;
+                                }
                             }
-                        }
-                    }        
-                    break;
+                        }        
+                        break;
 
-                case lldb::eStateCrashed:
-                    if (log)
-                        log->PutCString ("Process::RunThreadPlan(): execution crashed.");
-                    return_value = eExecutionInterrupted;
-                    break;
+                    case lldb::eStateCrashed:
+                        if (log)
+                            log->PutCString ("Process::RunThreadPlan(): execution crashed.");
+                        return_value = eExecutionInterrupted;
+                        break;
 
-                case lldb::eStateRunning:
-                    do_resume = false;
-                    keep_going = true;
-                    break;
+                    case lldb::eStateRunning:
+                        do_resume = false;
+                        keep_going = true;
+                        break;
 
-                default:
+                    default:
+                        if (log)
+                            log->Printf("Process::RunThreadPlan(): execution stopped with unexpected state: %s.", StateAsCString(stop_state));
+                            
+                        if (stop_state == eStateExited)
+                            event_to_broadcast_sp = event_sp;
+                            
+                        errors.Printf ("Execution stopped with unexpected state.");
+                        return_value = eExecutionInterrupted;
+                        break;
+                    }
+                    if (keep_going)
+                        continue;
+                    else
+                        break;
+                } 
+                else
+                {
                     if (log)
-                        log->Printf("Process::RunThreadPlan(): execution stopped with unexpected state: %s.", StateAsCString(stop_state));
-                        
-                    errors.Printf ("Execution stopped with unexpected state.");
+                        log->PutCString ("Process::RunThreadPlan(): got_event was true, but the event pointer was null.  How odd...");
                     return_value = eExecutionInterrupted;
                     break;
                 }
-                if (keep_going)
-                    continue;
-                else
-                    break;
-            } 
+            }
             else
             {
-                if (log)
-                    log->PutCString ("Process::RunThreadPlan(): got_event was true, but the event pointer was null.  How odd...");
-                return_value = 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)
-                {
-                    if (first_timeout)
-                        log->Printf ("Process::RunThreadPlan(): Running function with timeout: %d timed out, "
-                                     "trying with all threads enabled.",
-                                     single_thread_timeout_usec);
+                // 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)
+                    {
+                        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(): Restarting function with all threads enabled "
-                                     "and timeout: %d timed out.",
+                        log->Printf ("Process::RunThreadPlan(): Running function with timeout: %d timed out, "
+                                     "halt and abandoning execution.", 
                                      single_thread_timeout_usec);
                 }
-                else
-                    log->Printf ("Process::RunThreadPlan(): Running function with timeout: %d timed out, "
-                                 "halt and abandoning execution.", 
-                                 single_thread_timeout_usec);
-            }
-            
-            Error halt_error = Halt();
-            if (halt_error.Success())
-            {
-                if (log)
-                    log->PutCString ("Process::RunThreadPlan(): Halt succeeded.");
-                    
-                // 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)
+                Error halt_error = Halt();
+                if (halt_error.Success())
                 {
-                    stop_state = Process::ProcessEventData::GetStateFromEvent(event_sp.get());
                     if (log)
-                    {
-                        log->Printf ("Process::RunThreadPlan(): Stopped with event: %s", StateAsCString(stop_state));
-                        if (stop_state == lldb::eStateStopped 
-                            && Process::ProcessEventData::GetInterruptedFromEvent(event_sp.get()))
-                            log->PutCString ("    Event was the Halt interruption event.");
-                    }
-                    
-                    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:
+                        log->PutCString ("Process::RunThreadPlan(): Halt succeeded.");
                         
-                        if (thread->IsThreadPlanDone (thread_plan_sp.get()))
-                        {
-                            if (log)
-                                log->PutCString ("Process::RunThreadPlan(): Even though we timed out, the call plan was done.  "
-                                             "Exiting wait loop.");
-                            return_value = eExecutionCompleted;
-                            break;
-                        }
+                    // If halt succeeds, it always produces a stopped event.  Wait for that:
+                    
+                    real_timeout = TimeValue::Now();
+                    real_timeout.OffsetWithMicroSeconds(500000);
 
-                        if (!try_all_threads)
+                    got_event = listener.WaitForEvent(&real_timeout, event_sp);
+                    
+                    if (got_event)
+                    {
+                        stop_state = Process::ProcessEventData::GetStateFromEvent(event_sp.get());
+                        if (log)
                         {
-                            if (log)
-                                log->PutCString ("Process::RunThreadPlan(): try_all_threads was false, we stopped so now we're quitting.");
-                            return_value = eExecutionInterrupted;
-                            break;
+                            log->Printf ("Process::RunThreadPlan(): Stopped with event: %s", StateAsCString(stop_state));
+                            if (stop_state == lldb::eStateStopped 
+                                && Process::ProcessEventData::GetInterruptedFromEvent(event_sp.get()))
+                                log->PutCString ("    Event was the Halt interruption event.");
                         }
                         
-                        if (first_timeout)
+                        if (stop_state == lldb::eStateStopped)
                         {
-                            // 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->PutCString ("Process::RunThreadPlan(): about to resume.");
+                            // 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 (thread->IsThreadPlanDone (thread_plan_sp.get()))
+                            {
+                                if (log)
+                                    log->PutCString ("Process::RunThreadPlan(): Even though we timed out, the call plan was done.  "
+                                                 "Exiting wait loop.");
+                                return_value = eExecutionCompleted;
+                                break;
+                            }
 
-                            continue;
-                        }
-                        else
-                        {
-                            // Running all threads failed, so return Interrupted.
-                            if (log)
-                                log->PutCString("Process::RunThreadPlan(): running all threads timed out.");
-                            return_value = eExecutionInterrupted;
-                            break;
+                            if (!try_all_threads)
+                            {
+                                if (log)
+                                    log->PutCString ("Process::RunThreadPlan(): try_all_threads was false, we stopped so now we're quitting.");
+                                return_value = eExecutionInterrupted;
+                                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->PutCString ("Process::RunThreadPlan(): about to resume.");
+
+                                continue;
+                            }
+                            else
+                            {
+                                // Running all threads failed, so return Interrupted.
+                                if (log)
+                                    log->PutCString("Process::RunThreadPlan(): running all threads timed out.");
+                                return_value = eExecutionInterrupted;
+                                break;
+                            }
                         }
                     }
-                }
-                else
-                {   if (log)
-                        log->PutCString("Process::RunThreadPlan(): halt said it succeeded, but I got no event.  "
-                                "I'm getting out of here passing Interrupted.");
-                    return_value = 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 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)
-                {
-                    // This is not going anywhere, bag out.
-                    if (log)
-                        log->PutCString ("Process::RunThreadPlan(): halt failed: and waiting for the stopped event failed.");
-                    return_value = eExecutionInterrupted;
-                    break;                
+                    else
+                    {   if (log)
+                            log->PutCString("Process::RunThreadPlan(): halt said it succeeded, but I got no event.  "
+                                    "I'm getting out of here passing Interrupted.");
+                        return_value = eExecutionInterrupted;
+                        break;
+                    }
                 }
                 else
                 {
-                    stop_state = Process::ProcessEventData::GetStateFromEvent(event_sp.get());
+                    // 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->PutCString ("Process::RunThreadPlan(): halt failed: but then I got a stopped event.  Whatever...");
-                    if (stop_state == lldb::eStateStopped)
+                        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)
                     {
-                        // 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 (thread->IsThreadPlanDone (thread_plan_sp.get()))
+                        // This is not going anywhere, bag out.
+                        if (log)
+                            log->PutCString ("Process::RunThreadPlan(): halt failed: and waiting for the stopped event failed.");
+                        return_value = eExecutionInterrupted;
+                        break;                
+                    }
+                    else
+                    {
+                        stop_state = Process::ProcessEventData::GetStateFromEvent(event_sp.get());
+                        if (log)
+                            log->PutCString ("Process::RunThreadPlan(): halt failed: but then I got a stopped event.  Whatever...");
+                        if (stop_state == lldb::eStateStopped)
                         {
-                            if (log)
-                                log->PutCString ("Process::RunThreadPlan(): Even though we timed out, the call plan was done.  "
-                                             "Exiting wait loop.");
-                            return_value = 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 (thread->IsThreadPlanDone (thread_plan_sp.get()))
+                            {
+                                if (log)
+                                    log->PutCString ("Process::RunThreadPlan(): Even though we timed out, the call plan was done.  "
+                                                 "Exiting wait loop.");
+                                return_value = 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->PutCString ("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->PutCString ("Process::RunThreadPlan(): About to resume.");
 
-                            continue;
+                                continue;
+                            }
+                            else
+                            {
+                                // Running all threads failed, so return Interrupted.
+                                if (log)
+                                    log->PutCString ("Process::RunThreadPlan(): running all threads timed out.");
+                                return_value = eExecutionInterrupted;
+                                break;
+                            }
                         }
                         else
                         {
-                            // Running all threads failed, so return Interrupted.
                             if (log)
-                                log->PutCString ("Process::RunThreadPlan(): running all threads timed out.");
+                                log->Printf ("Process::RunThreadPlan(): halt failed, I waited and didn't get"
+                                             " a stopped event, instead got %s.", StateAsCString(stop_state));
                             return_value = eExecutionInterrupted;
-                            break;
+                            break;                
                         }
                     }
-                    else
-                    {
-                        if (log)
-                            log->Printf ("Process::RunThreadPlan(): halt failed, I waited and didn't get"
-                                         " a stopped event, instead got %s.", StateAsCString(stop_state));
-                        return_value = eExecutionInterrupted;
-                        break;                
-                    }
                 }
-            }
 
-        }
+            }
+            
+        }  // END WAIT LOOP
         
-    }  // END WAIT LOOP
-    
-    // If we had to start up a temporary private state thread to run this thread plan, shut it down now.
-    if (IS_VALID_LLDB_HOST_THREAD(backup_private_state_thread))
-    {
-        StopPrivateStateThread();
-        Error error;
-        m_private_state_thread = backup_private_state_thread;
-        if (stopper_base_plan_sp != NULL)
+        // If we had to start up a temporary private state thread to run this thread plan, shut it down now.
+        if (IS_VALID_LLDB_HOST_THREAD(backup_private_state_thread))
         {
-            thread->DiscardThreadPlansUpToPlan(stopper_base_plan_sp);
-        }
-        m_public_state.SetValueNoLock(old_state);
-
-    }
-    
-    
-    // Now do some processing on the results of the run:
-    if (return_value == eExecutionInterrupted)
-    {
-        if (log)
-        {
-            StreamString s;
-            if (event_sp)
-                event_sp->Dump (&s);
-            else
+            StopPrivateStateThread();
+            Error error;
+            m_private_state_thread = backup_private_state_thread;
+            if (stopper_base_plan_sp != NULL)
             {
-                log->PutCString ("Process::RunThreadPlan(): Stop event that interrupted us is NULL.");
+                thread->DiscardThreadPlansUpToPlan(stopper_base_plan_sp);
             }
+            m_public_state.SetValueNoLock(old_state);
 
-            StreamString ts;
-
-            const char *event_explanation = NULL;                
-            
-            do 
+        }
+        
+        
+        // Now do some processing on the results of the run:
+        if (return_value == eExecutionInterrupted)
+        {
+            if (log)
             {
-                const Process::ProcessEventData *event_data = Process::ProcessEventData::GetEventDataFromEvent (event_sp.get());
-
-                if (!event_data)
+                StreamString s;
+                if (event_sp)
+                    event_sp->Dump (&s);
+                else
                 {
-                    event_explanation = "<no event data>";
-                    break;
+                    log->PutCString ("Process::RunThreadPlan(): Stop event that interrupted us is NULL.");
                 }
-                
-                Process *process = event_data->GetProcessSP().get();
 
-                if (!process)
-                {
-                    event_explanation = "<no process>";
-                    break;
-                }
-                
-                ThreadList &thread_list = process->GetThreadList();
-                
-                uint32_t num_threads = thread_list.GetSize();
-                uint32_t thread_index;
-                
-                ts.Printf("<%u threads> ", num_threads);
+                StreamString ts;
+
+                const char *event_explanation = NULL;                
                 
-                for (thread_index = 0;
-                     thread_index < num_threads;
-                     ++thread_index)
+                do 
                 {
-                    Thread *thread = thread_list.GetThreadAtIndex(thread_index).get();
+                    const Process::ProcessEventData *event_data = Process::ProcessEventData::GetEventDataFromEvent (event_sp.get());
+
+                    if (!event_data)
+                    {
+                        event_explanation = "<no event data>";
+                        break;
+                    }
                     
-                    if (!thread)
+                    Process *process = event_data->GetProcessSP().get();
+
+                    if (!process)
                     {
-                        ts.Printf("<?> ");
-                        continue;
+                        event_explanation = "<no process>";
+                        break;
                     }
                     
-                    ts.Printf("<0x%4.4llx ", thread->GetID());
-                    RegisterContext *register_context = thread->GetRegisterContext().get();
+                    ThreadList &thread_list = process->GetThreadList();
                     
-                    if (register_context)
-                        ts.Printf("[ip 0x%llx] ", register_context->GetPC());
-                    else
-                        ts.Printf("[ip unknown] ");
+                    uint32_t num_threads = thread_list.GetSize();
+                    uint32_t thread_index;
+                    
+                    ts.Printf("<%u threads> ", num_threads);
                     
-                    lldb::StopInfoSP stop_info_sp = thread->GetStopInfo();
-                    if (stop_info_sp)
+                    for (thread_index = 0;
+                         thread_index < num_threads;
+                         ++thread_index)
                     {
-                        const char *stop_desc = stop_info_sp->GetDescription();
-                        if (stop_desc)
-                            ts.PutCString (stop_desc);
+                        Thread *thread = thread_list.GetThreadAtIndex(thread_index).get();
+                        
+                        if (!thread)
+                        {
+                            ts.Printf("<?> ");
+                            continue;
+                        }
+                        
+                        ts.Printf("<0x%4.4llx ", 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(">");
                     }
-                    ts.Printf(">");
-                }
+                    
+                    event_explanation = ts.GetData();
+                } while (0);
                 
-                event_explanation = ts.GetData();
-            } while (0);
-            
-            if (log)
-            {
-                if (event_explanation)
-                    log->Printf("Process::RunThreadPlan(): execution interrupted: %s %s", s.GetData(), event_explanation);
+                if (log)
+                {
+                    if (event_explanation)
+                        log->Printf("Process::RunThreadPlan(): execution interrupted: %s %s", s.GetData(), event_explanation);
+                    else
+                        log->Printf("Process::RunThreadPlan(): execution interrupted: %s", s.GetData());
+                }                
+                    
+                if (discard_on_error && thread_plan_sp)
+                {
+                    if (log)
+                        log->Printf ("Process::RunThreadPlan: ExecutionInterrupted - discarding thread plans up to %p.", thread_plan_sp.get());
+                    thread->DiscardThreadPlansUpToPlan (thread_plan_sp);
+                    thread_plan_sp->SetPrivate (orig_plan_private);
+                }
                 else
-                    log->Printf("Process::RunThreadPlan(): execution interrupted: %s", s.GetData());
-            }                
+                {
+                    if (log)
+                        log->Printf ("Process::RunThreadPlan: ExecutionInterrupted - for plan: %p not discarding.", thread_plan_sp.get());
+
+                }
+            }
+        }
+        else if (return_value == eExecutionSetupError)
+        {
+            if (log)
+                log->PutCString("Process::RunThreadPlan(): execution set up error.");
                 
             if (discard_on_error && thread_plan_sp)
             {
-                if (log)
-                    log->Printf ("Process::RunThreadPlan: ExecutionInterrupted - discarding thread plans up to %p.", thread_plan_sp.get());
                 thread->DiscardThreadPlansUpToPlan (thread_plan_sp);
                 thread_plan_sp->SetPrivate (orig_plan_private);
             }
+        }
+        else
+        {
+            if (thread->IsThreadPlanDone (thread_plan_sp.get()))
+            {
+                if (log)
+                    log->PutCString("Process::RunThreadPlan(): thread plan is done");
+                return_value = eExecutionCompleted;
+            }
+            else if (thread->WasThreadPlanDiscarded (thread_plan_sp.get()))
+            {
+                if (log)
+                    log->PutCString("Process::RunThreadPlan(): thread plan was discarded");
+                return_value = eExecutionDiscarded;
+            }
             else
             {
                 if (log)
-                    log->Printf ("Process::RunThreadPlan: ExecutionInterrupted - for plan: %p not discarding.", thread_plan_sp.get());
-
+                    log->PutCString("Process::RunThreadPlan(): thread plan stopped in mid course");
+                if (discard_on_error && thread_plan_sp)
+                {
+                    if (log)
+                        log->PutCString("Process::RunThreadPlan(): discarding thread plan 'cause discard_on_error is set.");
+                    thread->DiscardThreadPlansUpToPlan (thread_plan_sp);
+                    thread_plan_sp->SetPrivate (orig_plan_private);
+                }
             }
         }
-    }
-    else if (return_value == eExecutionSetupError)
-    {
-        if (log)
-            log->PutCString("Process::RunThreadPlan(): execution set up error.");
-            
-        if (discard_on_error && thread_plan_sp)
-        {
-            thread->DiscardThreadPlansUpToPlan (thread_plan_sp);
-            thread_plan_sp->SetPrivate (orig_plan_private);
-        }
-    }
-    else
-    {
-        if (thread->IsThreadPlanDone (thread_plan_sp.get()))
+                    
+        // Thread we ran the function in may have gone away because we ran the target
+        // Check that it's still there, and if it is put it back in the context.  Also restore the
+        // frame in the context if it is still present.
+        thread = GetThreadList().FindThreadByIndexID(thread_idx_id, true).get();
+        if (thread)
         {
-            if (log)
-                log->PutCString("Process::RunThreadPlan(): thread plan is done");
-            return_value = eExecutionCompleted;
+            exe_ctx.SetFrameSP (thread->GetFrameWithStackID (ctx_frame_id));
         }
-        else if (thread->WasThreadPlanDiscarded (thread_plan_sp.get()))
-        {
-            if (log)
-                log->PutCString("Process::RunThreadPlan(): thread plan was discarded");
-            return_value = eExecutionDiscarded;
-        }
-        else
+        
+        // Also restore the current process'es selected frame & thread, since this function calling may
+        // be done behind the user's back.
+        
+        if (selected_tid != LLDB_INVALID_THREAD_ID)
         {
-            if (log)
-                log->PutCString("Process::RunThreadPlan(): thread plan stopped in mid course");
-            if (discard_on_error && thread_plan_sp)
+            if (GetThreadList().SetSelectedThreadByIndexID (selected_tid) && selected_stack_id.IsValid())
             {
-                if (log)
-                    log->PutCString("Process::RunThreadPlan(): discarding thread plan 'cause discard_on_error is set.");
-                thread->DiscardThreadPlansUpToPlan (thread_plan_sp);
-                thread_plan_sp->SetPrivate (orig_plan_private);
+                // We were able to restore the selected thread, now restore the frame:
+                StackFrameSP old_frame_sp = GetThreadList().GetSelectedThread()->GetFrameWithStackID(selected_stack_id);
+                if (old_frame_sp)
+                    GetThreadList().GetSelectedThread()->SetSelectedFrame(old_frame_sp.get());
             }
         }
     }
-                
-    // Thread we ran the function in may have gone away because we ran the target
-    // Check that it's still there, and if it is put it back in the context.  Also restore the
-    // frame in the context if it is still present.
-    thread = GetThreadList().FindThreadByIndexID(thread_idx_id, true).get();
-    if (thread)
-    {
-        exe_ctx.SetFrameSP (thread->GetFrameWithStackID (ctx_frame_id));
-    }
     
-    // Also restore the current process'es selected frame & thread, since this function calling may
-    // be done behind the user's back.
+    // If the process exited during the run of the thread plan, notify everyone.
     
-    if (selected_tid != LLDB_INVALID_THREAD_ID)
+    if (event_to_broadcast_sp)
     {
-        if (GetThreadList().SetSelectedThreadByIndexID (selected_tid) && selected_stack_id.IsValid())
-        {
-            // We were able to restore the selected thread, now restore the frame:
-            StackFrameSP old_frame_sp = GetThreadList().GetSelectedThread()->GetFrameWithStackID(selected_stack_id);
-            if (old_frame_sp)
-                GetThreadList().GetSelectedThread()->SetSelectedFrame(old_frame_sp.get());
-        }
+        if (log)
+            log->PutCString("Process::RunThreadPlan(): rebroadcasting event.");
+        BroadcastEvent(event_to_broadcast_sp);
     }
     
     return return_value;





More information about the lldb-commits mailing list