[Lldb-commits] [lldb] r174793 - Reworked the way Process::RunThreadPlan and the ThreadPlanCallFunction interoperate to fix problems where

Jim Ingham jingham at apple.com
Wed Feb 13 11:42:51 PST 2013


Yes, that's a little bit of a weird test, since it has to switch the debugger into async mode, run "continue" and then switch it back, in the middle of handling a breakpoint command.

Jim


On Feb 13, 2013, at 10:54 AM, "Malea, Daniel" <daniel.malea at intel.com> wrote:

> Thanks for looking into it Jim. I also noticed some cases (very hard to reproduce) where events would just disappear and never get delivered…I'm afraid I don't have any more information at the moment. If i find anything out, I'll post it to the list.
> 
> In the meantime, I'm going to go ahead and disable that test-case on Linux so we can get the rest of the tests running.
> 
> 
> Dan
> 
> 
> 
> On 2013-02-13, at 1:15 PM, Jim Ingham <jingham at apple.com>
> wrote:
> 
>> Humm...  I'll try putting this assert in the ProcessGDBRemote::DoResume and see if I can reproduce this.  
>> 
>> I found a couple of cases where our attempts to coalesce events was incorrect causing us to occasionally not broadcast events that we should have, and then there were various workarounds for that that just exacerbated the problem.  It is quite possible that there is still somewhere that is getting this wrong.
>> 
>> Jim
>> 
>> On Feb 12, 2013, at 3:00 PM, "Malea, Daniel" <daniel.malea at intel.com> wrote:
>> 
>>> Hi Jim,
>>> 
>>> This commit appears to introduce some new test crashes on Linux in functionalities/conditional_break. The crashes don't appear to be always reproducible, which leads me to believe there's a race condition introduced somewhere, but in all cases the test crashes or fails.
>>> 
>>> Here's all the info I have at the moment about the 3 ways in which the test does not pass:
>>> 
>>> 1. ProcessPOSIX.cpp:223: virtual lldb_private::Error ProcessPOSIX::DoResume(): Assertion `state == eStateStopped || state == eStateCrashed' failed.
>>> - it seems state == eStateRunning at this point
>>> - looks like other Process plugin implementations don't assert that state == [Stopped|Crashed]. In fact, ProcessKDP seems to handle eStateRunning in DoResume. Is the assert wrong in this case, and is ProcessPOSIX supposed to handle DoResume when the process is already running? It seems there's an unexpected call to DoResume otherwise.
>>> 
>>> 2. POSIXThread.cpp:254: void POSIXThread::BreakNotify(const ProcessMessage&): Assertion `bp_site' failed.
>>> - In this case, it looks like the PC is one byte less than where the breakpoint is set, which is why the call to GetBreakpointSiteList().FindByAddress(pc) fails to return the breakpoint location.
>>> - I notice there's logic in RegisterContext_x86_64 to update the PC after a breakpoint has been hit by decrementing one byte. Almost looks like this is happening twice for some reason…
>>> 
>>> 3. The test case fails due to:
>>> 
>>> runCmd: frame info
>>> output: frame #0: 0x00000000004005a4 a.out`c(val=2) + 4 at main.c:39
>>> 
>>> 
>>> Expecting sub string: a.out`c
>>> Matched
>>> 
>>> runCmd: frame select 1
>>> runCmd failed!
>>> error: Frame index (1) out of range.
>>> 
>>> I'm not really sure why case the testcase fails with #3 -- it's rather difficult to reproduce.
>>> Also, the corresponding tests (r174897) are also failing. Wondering if there's something obvious I'm missing -- perhaps some piece of functionality that needs to be implemented on Linux for your change to work?
>>> 
>>> Any hints are appreciated!
>>> 
>>> 
>>> 
>>> Thanks,
>>> Dan
>>> 
>>> On 2013-02-08, at 8:29 PM, Jim Ingham <jingham at apple.com<mailto:jingham at apple.com>> wrote:
>>> 
>>> Author: jingham
>>> Date: Fri Feb  8 19:29:05 2013
>>> New Revision: 174793
>>> 
>>> URL: http://llvm.org/viewvc/llvm-project?rev=174793&view=rev
>>> Log:
>>> Reworked the way Process::RunThreadPlan and the ThreadPlanCallFunction interoperate to fix problems where
>>> hitting auto-continue signals while running a thread plan would cause us to lose control of the debug
>>> session.
>>> 
>>> <rdar://problem/12993641>
>>> 
>>> Modified:
>>> lldb/trunk/include/lldb/API/SBExpressionOptions.h
>>> lldb/trunk/include/lldb/API/SBProcess.h
>>> lldb/trunk/include/lldb/Target/Process.h
>>> lldb/trunk/include/lldb/Target/StopInfo.h
>>> lldb/trunk/include/lldb/Target/ThreadPlan.h
>>> lldb/trunk/include/lldb/Target/ThreadPlanBase.h
>>> lldb/trunk/include/lldb/Target/ThreadPlanCallFunction.h
>>> lldb/trunk/include/lldb/Target/ThreadPlanRunToAddress.h
>>> lldb/trunk/include/lldb/Target/ThreadPlanStepInRange.h
>>> lldb/trunk/include/lldb/Target/ThreadPlanStepInstruction.h
>>> lldb/trunk/include/lldb/Target/ThreadPlanStepOut.h
>>> lldb/trunk/include/lldb/Target/ThreadPlanStepOverBreakpoint.h
>>> lldb/trunk/include/lldb/Target/ThreadPlanStepOverRange.h
>>> lldb/trunk/include/lldb/Target/ThreadPlanStepThrough.h
>>> lldb/trunk/include/lldb/Target/ThreadPlanStepUntil.h
>>> lldb/trunk/scripts/Python/interface/SBExpressionOptions.i
>>> lldb/trunk/scripts/Python/interface/SBProcess.i
>>> lldb/trunk/source/API/SBProcess.cpp
>>> lldb/trunk/source/Commands/CommandObjectProcess.cpp
>>> lldb/trunk/source/Expression/ClangUserExpression.cpp
>>> lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp
>>> lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.h
>>> lldb/trunk/source/Target/Process.cpp
>>> lldb/trunk/source/Target/StopInfo.cpp
>>> lldb/trunk/source/Target/Thread.cpp
>>> lldb/trunk/source/Target/ThreadPlanBase.cpp
>>> lldb/trunk/source/Target/ThreadPlanCallFunction.cpp
>>> lldb/trunk/source/Target/ThreadPlanRunToAddress.cpp
>>> lldb/trunk/source/Target/ThreadPlanStepInRange.cpp
>>> lldb/trunk/source/Target/ThreadPlanStepInstruction.cpp
>>> lldb/trunk/source/Target/ThreadPlanStepOut.cpp
>>> lldb/trunk/source/Target/ThreadPlanStepOverBreakpoint.cpp
>>> lldb/trunk/source/Target/ThreadPlanStepOverRange.cpp
>>> lldb/trunk/source/Target/ThreadPlanStepThrough.cpp
>>> lldb/trunk/source/Target/ThreadPlanStepUntil.cpp
>>> lldb/trunk/test/functionalities/conditional_break/conditional_break.py
>>> lldb/trunk/tools/driver/Driver.cpp
>>> 
>>> Modified: lldb/trunk/include/lldb/API/SBExpressionOptions.h
>>> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/API/SBExpressionOptions.h?rev=174793&r1=174792&r2=174793&view=diff
>>> ==============================================================================
>>> --- lldb/trunk/include/lldb/API/SBExpressionOptions.h (original)
>>> +++ lldb/trunk/include/lldb/API/SBExpressionOptions.h Fri Feb  8 19:29:05 2013
>>> @@ -40,13 +40,13 @@ public:
>>>  GetUnwindOnError () const;
>>> 
>>>  void
>>> -    SetUnwindOnError (bool unwind = false);
>>> +    SetUnwindOnError (bool unwind = true);
>>> 
>>>  bool
>>>  GetIgnoreBreakpoints () const;
>>> 
>>>  void
>>> -    SetIgnoreBreakpoints (bool ignore = false);
>>> +    SetIgnoreBreakpoints (bool ignore = true);
>>> 
>>>  lldb::DynamicValueType
>>>  GetFetchDynamicValue () const;
>>> 
>>> Modified: lldb/trunk/include/lldb/API/SBProcess.h
>>> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/API/SBProcess.h?rev=174793&r1=174792&r2=174793&view=diff
>>> ==============================================================================
>>> --- lldb/trunk/include/lldb/API/SBProcess.h (original)
>>> +++ lldb/trunk/include/lldb/API/SBProcess.h Fri Feb  8 19:29:05 2013
>>> @@ -234,6 +234,12 @@ public:
>>> 
>>>  static bool
>>>  GetRestartedFromEvent (const lldb::SBEvent &event);
>>> +
>>> +    static size_t
>>> +    GetNumRestartedReasonsFromEvent (const lldb::SBEvent &event);
>>> +
>>> +    static const char *
>>> +    GetRestartedReasonAtIndexFromEvent (const lldb::SBEvent &event, size_t idx);
>>> 
>>>  static lldb::SBProcess
>>>  GetProcessFromEvent (const lldb::SBEvent &event);
>>> 
>>> Modified: lldb/trunk/include/lldb/Target/Process.h
>>> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/Process.h?rev=174793&r1=174792&r2=174793&view=diff
>>> ==============================================================================
>>> --- lldb/trunk/include/lldb/Target/Process.h (original)
>>> +++ lldb/trunk/include/lldb/Target/Process.h Fri Feb  8 19:29:05 2013
>>> @@ -1446,6 +1446,22 @@ public:
>>>          {
>>>              return m_restarted;
>>>          }
>>> +
>>> +            size_t
>>> +            GetNumRestartedReasons ()
>>> +            {
>>> +                return m_restarted_reasons.size();
>>> +            }
>>> +
>>> +            const char *
>>> +            GetRestartedReasonAtIndex(size_t idx)
>>> +            {
>>> +                if (idx > m_restarted_reasons.size())
>>> +                    return NULL;
>>> +                else
>>> +                    return m_restarted_reasons[idx].c_str();
>>> +            }
>>> +
>>>          bool
>>>          GetInterrupted () const
>>>          {
>>> @@ -1469,6 +1485,15 @@ public:
>>> 
>>>          static bool
>>>          GetRestartedFromEvent (const Event *event_ptr);
>>> +
>>> +            static size_t
>>> +            GetNumRestartedReasons(const Event *event_ptr);
>>> +
>>> +            static const char *
>>> +            GetRestartedReasonAtIndex(const Event *event_ptr, size_t idx);
>>> +
>>> +            static void
>>> +            AddRestartedReason (Event *event_ptr, const char *reason);
>>> 
>>>          static void
>>>          SetRestartedInEvent (Event *event_ptr, bool new_value);
>>> @@ -1499,9 +1524,15 @@ public:
>>>          {
>>>              m_interrupted = new_value;
>>>          }
>>> +            void
>>> +            AddRestartedReason (const char *reason)
>>> +            {
>>> +                m_restarted_reasons.push_back(reason);
>>> +            }
>>> 
>>>          lldb::ProcessSP m_process_sp;
>>>          lldb::StateType m_state;
>>> +            std::vector<std::string> m_restarted_reasons;
>>>          bool m_restarted;  // For "eStateStopped" events, this is true if the target was automatically restarted.
>>>          int m_update_state;
>>>          bool m_interrupted;
>>> @@ -3543,7 +3574,8 @@ protected:
>>>  ReadWriteLock               m_run_lock;
>>>  Predicate<bool>             m_currently_handling_event;
>>>  bool                        m_finalize_called;
>>> -
>>> +    lldb::StateType             m_last_broadcast_state;   /// This helps with the Public event coalescing in ShouldBroadcastEvent.
>>> +
>>>  enum {
>>>      eCanJITDontKnow= 0,
>>>      eCanJITYes,
>>> @@ -3637,7 +3669,7 @@ private:
>>>  // For Process only
>>>  //------------------------------------------------------------------
>>>  void ControlPrivateStateThread (uint32_t signal);
>>> -
>>> +
>>>  DISALLOW_COPY_AND_ASSIGN (Process);
>>> 
>>> };
>>> 
>>> Modified: lldb/trunk/include/lldb/Target/StopInfo.h
>>> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/StopInfo.h?rev=174793&r1=174792&r2=174793&view=diff
>>> ==============================================================================
>>> --- lldb/trunk/include/lldb/Target/StopInfo.h (original)
>>> +++ lldb/trunk/include/lldb/Target/StopInfo.h Fri Feb  8 19:29:05 2013
>>> @@ -106,7 +106,32 @@ public:
>>>      else
>>>          m_description.clear();
>>>  }
>>> -
>>> +
>>> +    // Sometimes the thread plan logic will know that it wants a given stop to stop or not,
>>> +    // regardless of what the ordinary logic for that StopInfo would dictate.  The main example
>>> +    // of this is the ThreadPlanCallFunction, which for instance knows - based on how that particular
>>> +    // expression was executed - whether it wants all breakpoints to auto-continue or not.
>>> +    // Use OverrideShouldStop on the StopInfo to implement this.
>>> +
>>> +    void
>>> +    OverrideShouldStop (bool override_value)
>>> +    {
>>> +        m_override_set = true;
>>> +        m_override_value = override_value;
>>> +    }
>>> +
>>> +    bool
>>> +    GetOverrideShouldStop()
>>> +    {
>>> +        return m_override_set;
>>> +    }
>>> +
>>> +    bool
>>> +    GetOverriddenShouldStopValue ()
>>> +    {
>>> +        return m_override_value;
>>> +    }
>>> +
>>>  static lldb::StopInfoSP
>>>  CreateStopReasonWithBreakpointSiteID (Thread &thread, lldb::break_id_t break_id);
>>> 
>>> @@ -138,6 +163,7 @@ public:
>>> protected:
>>>  // Perform any action that is associated with this stop.  This is done as the
>>>  // Event is removed from the event queue.  ProcessEventData::DoOnRemoval does the job.
>>> +
>>>  virtual void
>>>  PerformAction (Event *event_ptr)
>>>  {
>>> @@ -163,6 +189,8 @@ protected:
>>>  uint32_t        m_resume_id; // This is the resume ID when we made this stop ID.
>>>  uint64_t        m_value;    // A generic value that can be used for things pertaining to this stop info
>>>  std::string     m_description; // A textual description describing this stop.
>>> +    bool            m_override_set;
>>> +    bool            m_override_value;
>>> 
>>>  // This determines whether the target has run since this stop info.
>>>  // N.B. running to evaluate a user expression does not count.
>>> 
>>> Modified: lldb/trunk/include/lldb/Target/ThreadPlan.h
>>> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/ThreadPlan.h?rev=174793&r1=174792&r2=174793&view=diff
>>> ==============================================================================
>>> --- lldb/trunk/include/lldb/Target/ThreadPlan.h (original)
>>> +++ lldb/trunk/include/lldb/Target/ThreadPlan.h Fri Feb  8 19:29:05 2013
>>> @@ -332,7 +332,7 @@ public:
>>>  ValidatePlan (Stream *error) = 0;
>>> 
>>>  virtual bool
>>> -    PlanExplainsStop () = 0;
>>> +    PlanExplainsStop (Event *event_ptr) = 0;
>>> 
>>>  bool
>>>  TracerExplainsStop ()
>>> 
>>> Modified: lldb/trunk/include/lldb/Target/ThreadPlanBase.h
>>> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/ThreadPlanBase.h?rev=174793&r1=174792&r2=174793&view=diff
>>> ==============================================================================
>>> --- lldb/trunk/include/lldb/Target/ThreadPlanBase.h (original)
>>> +++ lldb/trunk/include/lldb/Target/ThreadPlanBase.h Fri Feb  8 19:29:05 2013
>>> @@ -35,7 +35,7 @@ public:
>>> 
>>>  virtual void GetDescription (Stream *s, lldb::DescriptionLevel level);
>>>  virtual bool ValidatePlan (Stream *error);
>>> -    virtual bool PlanExplainsStop ();
>>> +    virtual bool PlanExplainsStop (Event *event_ptr);
>>>  virtual bool ShouldStop (Event *event_ptr);
>>>  virtual bool StopOthers ();
>>>  virtual lldb::StateType GetPlanRunState ();
>>> 
>>> Modified: lldb/trunk/include/lldb/Target/ThreadPlanCallFunction.h
>>> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/ThreadPlanCallFunction.h?rev=174793&r1=174792&r2=174793&view=diff
>>> ==============================================================================
>>> --- lldb/trunk/include/lldb/Target/ThreadPlanCallFunction.h (original)
>>> +++ lldb/trunk/include/lldb/Target/ThreadPlanCallFunction.h Fri Feb  8 19:29:05 2013
>>> @@ -59,10 +59,13 @@ public:
>>>  ValidatePlan (Stream *error);
>>> 
>>>  virtual bool
>>> -    PlanExplainsStop ();
>>> +    PlanExplainsStop (Event *event_ptr);
>>> 
>>>  virtual bool
>>>  ShouldStop (Event *event_ptr);
>>> +
>>> +    virtual Vote
>>> +    ShouldReportStop(Event *event_ptr);
>>> 
>>>  virtual bool
>>>  StopOthers ();
>>> 
>>> Modified: lldb/trunk/include/lldb/Target/ThreadPlanRunToAddress.h
>>> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/ThreadPlanRunToAddress.h?rev=174793&r1=174792&r2=174793&view=diff
>>> ==============================================================================
>>> --- lldb/trunk/include/lldb/Target/ThreadPlanRunToAddress.h (original)
>>> +++ lldb/trunk/include/lldb/Target/ThreadPlanRunToAddress.h Fri Feb  8 19:29:05 2013
>>> @@ -47,7 +47,7 @@ public:
>>>  ValidatePlan (Stream *error);
>>> 
>>>  virtual bool
>>> -    PlanExplainsStop ();
>>> +    PlanExplainsStop (Event *event_ptr);
>>> 
>>>  virtual bool
>>>  ShouldStop (Event *event_ptr);
>>> 
>>> Modified: lldb/trunk/include/lldb/Target/ThreadPlanStepInRange.h
>>> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/ThreadPlanStepInRange.h?rev=174793&r1=174792&r2=174793&view=diff
>>> ==============================================================================
>>> --- lldb/trunk/include/lldb/Target/ThreadPlanStepInRange.h (original)
>>> +++ lldb/trunk/include/lldb/Target/ThreadPlanStepInRange.h Fri Feb  8 19:29:05 2013
>>> @@ -61,7 +61,7 @@ public:
>>>  SetDefaultFlagValue (uint32_t new_value);
>>> 
>>>  virtual bool
>>> -    PlanExplainsStop ();
>>> +    PlanExplainsStop (Event *event_ptr);
>>> 
>>>  virtual bool WillResume (lldb::StateType resume_state, bool current_plan);
>>> 
>>> 
>>> Modified: lldb/trunk/include/lldb/Target/ThreadPlanStepInstruction.h
>>> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/ThreadPlanStepInstruction.h?rev=174793&r1=174792&r2=174793&view=diff
>>> ==============================================================================
>>> --- lldb/trunk/include/lldb/Target/ThreadPlanStepInstruction.h (original)
>>> +++ lldb/trunk/include/lldb/Target/ThreadPlanStepInstruction.h Fri Feb  8 19:29:05 2013
>>> @@ -27,7 +27,7 @@ public:
>>> 
>>>  virtual void GetDescription (Stream *s, lldb::DescriptionLevel level);
>>>  virtual bool ValidatePlan (Stream *error);
>>> -    virtual bool PlanExplainsStop ();
>>> +    virtual bool PlanExplainsStop (Event *event_ptr);
>>>  virtual bool ShouldStop (Event *event_ptr);
>>>  virtual bool StopOthers ();
>>>  virtual lldb::StateType GetPlanRunState ();
>>> 
>>> Modified: lldb/trunk/include/lldb/Target/ThreadPlanStepOut.h
>>> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/ThreadPlanStepOut.h?rev=174793&r1=174792&r2=174793&view=diff
>>> ==============================================================================
>>> --- lldb/trunk/include/lldb/Target/ThreadPlanStepOut.h (original)
>>> +++ lldb/trunk/include/lldb/Target/ThreadPlanStepOut.h Fri Feb  8 19:29:05 2013
>>> @@ -34,7 +34,7 @@ public:
>>> 
>>>  virtual void GetDescription (Stream *s, lldb::DescriptionLevel level);
>>>  virtual bool ValidatePlan (Stream *error);
>>> -    virtual bool PlanExplainsStop ();
>>> +    virtual bool PlanExplainsStop (Event *event_ptr);
>>>  virtual bool ShouldStop (Event *event_ptr);
>>>  virtual bool StopOthers ();
>>>  virtual lldb::StateType GetPlanRunState ();
>>> 
>>> Modified: lldb/trunk/include/lldb/Target/ThreadPlanStepOverBreakpoint.h
>>> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/ThreadPlanStepOverBreakpoint.h?rev=174793&r1=174792&r2=174793&view=diff
>>> ==============================================================================
>>> --- lldb/trunk/include/lldb/Target/ThreadPlanStepOverBreakpoint.h (original)
>>> +++ lldb/trunk/include/lldb/Target/ThreadPlanStepOverBreakpoint.h Fri Feb  8 19:29:05 2013
>>> @@ -27,7 +27,7 @@ public:
>>>  ThreadPlanStepOverBreakpoint (Thread &thread);
>>>  virtual void GetDescription (Stream *s, lldb::DescriptionLevel level);
>>>  virtual bool ValidatePlan (Stream *error);
>>> -    virtual bool PlanExplainsStop ();
>>> +    virtual bool PlanExplainsStop (Event *event_ptr);
>>>  virtual bool ShouldStop (Event *event_ptr);
>>>  virtual bool StopOthers ();
>>>  virtual lldb::StateType GetPlanRunState ();
>>> 
>>> Modified: lldb/trunk/include/lldb/Target/ThreadPlanStepOverRange.h
>>> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/ThreadPlanStepOverRange.h?rev=174793&r1=174792&r2=174793&view=diff
>>> ==============================================================================
>>> --- lldb/trunk/include/lldb/Target/ThreadPlanStepOverRange.h (original)
>>> +++ lldb/trunk/include/lldb/Target/ThreadPlanStepOverRange.h Fri Feb  8 19:29:05 2013
>>> @@ -34,7 +34,7 @@ public:
>>> 
>>>  virtual void GetDescription (Stream *s, lldb::DescriptionLevel level);
>>>  virtual bool ShouldStop (Event *event_ptr);
>>> -    virtual bool PlanExplainsStop ();
>>> +    virtual bool PlanExplainsStop (Event *event_ptr);
>>>  virtual bool WillResume (lldb::StateType resume_state, bool current_plan);
>>> 
>>> protected:
>>> 
>>> Modified: lldb/trunk/include/lldb/Target/ThreadPlanStepThrough.h
>>> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/ThreadPlanStepThrough.h?rev=174793&r1=174792&r2=174793&view=diff
>>> ==============================================================================
>>> --- lldb/trunk/include/lldb/Target/ThreadPlanStepThrough.h (original)
>>> +++ lldb/trunk/include/lldb/Target/ThreadPlanStepThrough.h Fri Feb  8 19:29:05 2013
>>> @@ -26,7 +26,7 @@ public:
>>> 
>>>  virtual void GetDescription (Stream *s, lldb::DescriptionLevel level);
>>>  virtual bool ValidatePlan (Stream *error);
>>> -    virtual bool PlanExplainsStop ();
>>> +    virtual bool PlanExplainsStop (Event *event_ptr);
>>>  virtual bool ShouldStop (Event *event_ptr);
>>>  virtual bool StopOthers ();
>>>  virtual lldb::StateType GetPlanRunState ();
>>> 
>>> Modified: lldb/trunk/include/lldb/Target/ThreadPlanStepUntil.h
>>> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/ThreadPlanStepUntil.h?rev=174793&r1=174792&r2=174793&view=diff
>>> ==============================================================================
>>> --- lldb/trunk/include/lldb/Target/ThreadPlanStepUntil.h (original)
>>> +++ lldb/trunk/include/lldb/Target/ThreadPlanStepUntil.h Fri Feb  8 19:29:05 2013
>>> @@ -27,7 +27,7 @@ public:
>>> 
>>>  virtual void GetDescription (Stream *s, lldb::DescriptionLevel level);
>>>  virtual bool ValidatePlan (Stream *error);
>>> -    virtual bool PlanExplainsStop ();
>>> +    virtual bool PlanExplainsStop (Event *event_ptr);
>>>  virtual bool ShouldStop (Event *event_ptr);
>>>  virtual bool StopOthers ();
>>>  virtual lldb::StateType GetPlanRunState ();
>>> 
>>> Modified: lldb/trunk/scripts/Python/interface/SBExpressionOptions.i
>>> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/scripts/Python/interface/SBExpressionOptions.i?rev=174793&r1=174792&r2=174793&view=diff
>>> ==============================================================================
>>> --- lldb/trunk/scripts/Python/interface/SBExpressionOptions.i (original)
>>> +++ lldb/trunk/scripts/Python/interface/SBExpressionOptions.i Fri Feb  8 19:29:05 2013
>>> @@ -39,7 +39,7 @@ public:
>>>  %feature("docstring", "Sets whether to unwind the expression stack on error.") SetUnwindOnError;
>>> 
>>>  void
>>> -    SetUnwindOnError (bool unwind = false);
>>> +    SetUnwindOnError (bool unwind = true);
>>> 
>>>  bool
>>>  GetIgnoreBreakpoints () const;
>>> @@ -47,7 +47,7 @@ public:
>>>  %feature("docstring", "Sets whether to ignore breakpoint hits while running expressions.") SetUnwindOnError;
>>> 
>>>  void
>>> -    SetIgnoreBreakpoints (bool ignore = false);
>>> +    SetIgnoreBreakpoints (bool ignore = true);
>>> 
>>>  lldb::DynamicValueType
>>>  GetFetchDynamicValue () const;
>>> 
>>> Modified: lldb/trunk/scripts/Python/interface/SBProcess.i
>>> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/scripts/Python/interface/SBProcess.i?rev=174793&r1=174792&r2=174793&view=diff
>>> ==============================================================================
>>> --- lldb/trunk/scripts/Python/interface/SBProcess.i (original)
>>> +++ lldb/trunk/scripts/Python/interface/SBProcess.i Fri Feb  8 19:29:05 2013
>>> @@ -328,6 +328,12 @@ public:
>>>  static bool
>>>  GetRestartedFromEvent (const lldb::SBEvent &event);
>>> 
>>> +    static size_t
>>> +    GetNumRestartedReasonsFromEvent (const lldb::SBEvent &event);
>>> +
>>> +    static const char *
>>> +    GetRestartedReasonAtIndexFromEvent (const lldb::SBEvent &event, size_t idx);
>>> +
>>>  static lldb::SBProcess
>>>  GetProcessFromEvent (const lldb::SBEvent &event);
>>> 
>>> 
>>> Modified: lldb/trunk/source/API/SBProcess.cpp
>>> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/API/SBProcess.cpp?rev=174793&r1=174792&r2=174793&view=diff
>>> ==============================================================================
>>> --- lldb/trunk/source/API/SBProcess.cpp (original)
>>> +++ lldb/trunk/source/API/SBProcess.cpp Fri Feb  8 19:29:05 2013
>>> @@ -909,6 +909,18 @@ SBProcess::GetRestartedFromEvent (const
>>>  return Process::ProcessEventData::GetRestartedFromEvent (event.get());
>>> }
>>> 
>>> +size_t
>>> +SBProcess::GetNumRestartedReasonsFromEvent (const lldb::SBEvent &event)
>>> +{
>>> +    return Process::ProcessEventData::GetNumRestartedReasons(event.get());
>>> +}
>>> +
>>> +const char *
>>> +SBProcess::GetRestartedReasonAtIndexFromEvent (const lldb::SBEvent &event, size_t idx)
>>> +{
>>> +    return Process::ProcessEventData::GetRestartedReasonAtIndex(event.get(), idx);
>>> +}
>>> +
>>> SBProcess
>>> SBProcess::GetProcessFromEvent (const SBEvent &event)
>>> {
>>> 
>>> Modified: lldb/trunk/source/Commands/CommandObjectProcess.cpp
>>> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectProcess.cpp?rev=174793&r1=174792&r2=174793&view=diff
>>> ==============================================================================
>>> --- lldb/trunk/source/Commands/CommandObjectProcess.cpp (original)
>>> +++ lldb/trunk/source/Commands/CommandObjectProcess.cpp Fri Feb  8 19:29:05 2013
>>> @@ -199,6 +199,11 @@ protected:
>>>      if (environment.GetArgumentCount() > 0)
>>>          m_options.launch_info.GetEnvironmentEntries ().AppendArguments (environment);
>>> 
>>> +        // Get the value of synchronous execution here.  If you wait till after you have started to
>>> +        // run, then you could have hit a breakpoint, whose command might switch the value, and
>>> +        // then you'll pick up that incorrect value.
>>> +        bool synchronous_execution = m_interpreter.GetSynchronous ();
>>> +
>>>      // Finalize the file actions, and if none were given, default to opening
>>>      // up a pseudo terminal
>>>      const bool default_to_use_pty = true;
>>> @@ -258,7 +263,6 @@ protected:
>>>                  error = process->Resume();
>>>                  if (error.Success())
>>>                  {
>>> -                        bool synchronous_execution = m_interpreter.GetSynchronous ();
>>>                      if (synchronous_execution)
>>>                      {
>>>                          state = process->WaitForProcessToStop (NULL);
>>> 
>>> Modified: lldb/trunk/source/Expression/ClangUserExpression.cpp
>>> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/ClangUserExpression.cpp?rev=174793&r1=174792&r2=174793&view=diff
>>> ==============================================================================
>>> --- lldb/trunk/source/Expression/ClangUserExpression.cpp (original)
>>> +++ lldb/trunk/source/Expression/ClangUserExpression.cpp Fri Feb  8 19:29:05 2013
>>> @@ -703,7 +703,7 @@ ClangUserExpression::Execute (Stream &er
>>>      }
>>> 
>>>      const bool stop_others = true;
>>> -        const bool try_all_threads = true;
>>> +        const bool try_all_threads = run_others;
>>> 
>>>      Address wrapper_address (m_jit_start_addr);
>>>      lldb::ThreadPlanSP call_plan_sp(new ThreadPlanCallUserExpression (exe_ctx.GetThreadRef(),
>>> 
>>> Modified: lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp
>>> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp?rev=174793&r1=174792&r2=174793&view=diff
>>> ==============================================================================
>>> --- lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp (original)
>>> +++ lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp Fri Feb  8 19:29:05 2013
>>> @@ -126,7 +126,7 @@ AppleThreadPlanStepThroughObjCTrampoline
>>> }
>>> 
>>> bool
>>> -AppleThreadPlanStepThroughObjCTrampoline::PlanExplainsStop ()
>>> +AppleThreadPlanStepThroughObjCTrampoline::PlanExplainsStop (Event *event_ptr)
>>> {
>>>  // If we get asked to explain the stop it will be because something went
>>>  // wrong (like the implementation for selector function crashed...  We're going
>>> 
>>> Modified: lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.h
>>> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.h?rev=174793&r1=174792&r2=174793&view=diff
>>> ==============================================================================
>>> --- lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.h (original)
>>> +++ lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.h Fri Feb  8 19:29:05 2013
>>> @@ -46,7 +46,7 @@ public:
>>>  ValidatePlan (Stream *error);
>>> 
>>>  virtual bool
>>> -    PlanExplainsStop ();
>>> +    PlanExplainsStop (Event *event_ptr);
>>> 
>>> 
>>>  virtual lldb::StateType
>>> 
>>> Modified: lldb/trunk/source/Target/Process.cpp
>>> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/Process.cpp?rev=174793&r1=174792&r2=174793&view=diff
>>> ==============================================================================
>>> --- lldb/trunk/source/Target/Process.cpp (original)
>>> +++ lldb/trunk/source/Target/Process.cpp Fri Feb  8 19:29:05 2013
>>> @@ -1021,6 +1021,7 @@ Process::Process(Target &target, Listene
>>>  m_run_lock (),
>>>  m_currently_handling_event(false),
>>>  m_finalize_called(false),
>>> +    m_last_broadcast_state (eStateInvalid),
>>>  m_can_jit(eCanJITDontKnow)
>>> {
>>>  CheckInWithManager ();
>>> @@ -3146,9 +3147,9 @@ Process::ConnectRemote (Stream *strm, co
>>> Error
>>> Process::PrivateResume ()
>>> {
>>> -    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS|LIBLLDB_LOG_STEP));
>>> +    LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_PROCESS|LIBLLDB_LOG_STEP));
>>>  if (log)
>>> -        log->Printf("Process::Resume() m_stop_id = %u, public state: %s private state: %s",
>>> +        log->Printf("Process::PrivateResume() m_stop_id = %u, public state: %s private state: %s",
>>>                  m_mod_id.GetStopID(),
>>>                  StateAsCString(m_public_state.GetValue()),
>>>                  StateAsCString(m_private_state.GetValue()));
>>> @@ -3170,7 +3171,7 @@ Process::PrivateResume ()
>>>          // Last thing, do the PreResumeActions.
>>>          if (!RunPreResumeActions())
>>>          {
>>> -                error.SetErrorStringWithFormat ("Process::Resume PreResumeActions failed, not resuming.");
>>> +                error.SetErrorStringWithFormat ("Process::PrivateResume PreResumeActions failed, not resuming.");
>>>          }
>>>          else
>>>          {
>>> @@ -3197,7 +3198,7 @@ Process::PrivateResume ()
>>>      }
>>>  }
>>>  else if (log)
>>> -        log->Printf ("Process::WillResume() got an error \"%s\".", error.AsCString("<unknown error>"));
>>> +        log->Printf ("Process::PrivateResume() got an error \"%s\".", error.AsCString("<unknown error>"));
>>>  return error;
>>> }
>>> 
>>> @@ -3422,8 +3423,8 @@ Process::ShouldBroadcastEvent (Event *ev
>>> {
>>>  const StateType state = Process::ProcessEventData::GetStateFromEvent (event_ptr);
>>>  bool return_value = true;
>>> -    LogSP log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EVENTS));
>>> -
>>> +    LogSP log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_EVENTS | LIBLLDB_LOG_PROCESS));
>>> +
>>>  switch (state)
>>>  {
>>>      case eStateConnected:
>>> @@ -3448,7 +3449,7 @@ Process::ShouldBroadcastEvent (Event *ev
>>>          // stopped -> running: Report except when there is one or more no votes
>>>          //     and no yes votes.
>>>          SynchronouslyNotifyStateChanged (state);
>>> -            switch (m_public_state.GetValue())
>>> +            switch (m_last_broadcast_state)
>>>          {
>>>              case eStateRunning:
>>>              case eStateStepping:
>>> @@ -3490,32 +3491,50 @@ Process::ShouldBroadcastEvent (Event *ev
>>>          if (ProcessEventData::GetInterruptedFromEvent (event_ptr))
>>>          {
>>>              if (log)
>>> -                    log->Printf ("Process::ShouldBroadcastEvent (%p) stopped due to an interrupt, state: %s", event_ptr, StateAsCString(state));
>>> -                return true;
>>> +                    log->Printf ("Process::ShouldBroadcastEvent (%p) stopped due to an interrupt, state: %s",
>>> +                                 event_ptr,
>>> +                                 StateAsCString(state));
>>> +                return_value = true;
>>>          }
>>>          else
>>>          {
>>> -
>>> -                if (m_thread_list.ShouldStop (event_ptr) == false)
>>> +                // It makes no sense to ask "ShouldStop" if we've already been restarted...
>>> +                // Asking the thread list is also not likely to go well, since we are running again.
>>> +                // So in that case just report the event.
>>> +
>>> +                bool was_restarted = ProcessEventData::GetRestartedFromEvent (event_ptr);
>>> +                bool should_resume = false;
>>> +                if (!was_restarted)
>>> +                    should_resume = m_thread_list.ShouldStop (event_ptr) == false;
>>> +                if (was_restarted || should_resume)
>>>              {
>>> -                    // ShouldStop may have restarted the target already.  If so, don't
>>> -                    // resume it twice.
>>> -                    bool was_restarted = ProcessEventData::GetRestartedFromEvent (event_ptr);
>>> -                    switch (m_thread_list.ShouldReportStop (event_ptr))
>>> +                    Vote stop_vote = m_thread_list.ShouldReportStop (event_ptr);
>>> +                    if (log)
>>> +                        log->Printf ("Process::ShouldBroadcastEvent: should_stop: %i state: %s was_restarted: %i stop_vote: %d.",
>>> +                                     should_resume,
>>> +                                     StateAsCString(state),
>>> +                                     was_restarted,
>>> +                                     stop_vote);
>>> +
>>> +                    switch (stop_vote)
>>>                  {
>>>                      case eVoteYes:
>>> -                            Process::ProcessEventData::SetRestartedInEvent (event_ptr, true);
>>> -                            // Intentional fall-through here.
>>> +                            return_value = true;
>>> +                            break;
>>>                      case eVoteNoOpinion:
>>>                      case eVoteNo:
>>>                          return_value = false;
>>>                          break;
>>>                  }
>>> -
>>> -                    if (log)
>>> -                        log->Printf ("Process::ShouldBroadcastEvent (%p) Restarting process from state: %s", event_ptr, StateAsCString(state));
>>> +
>>>                  if (!was_restarted)
>>> +                    {
>>> +                        if (log)
>>> +                            log->Printf ("Process::ShouldBroadcastEvent (%p) Restarting process from state: %s", event_ptr, StateAsCString(state));
>>> +                        ProcessEventData::SetRestartedInEvent(event_ptr, true);
>>>                      PrivateResume ();
>>> +                    }
>>> +
>>>              }
>>>              else
>>>              {
>>> @@ -3524,10 +3543,25 @@ Process::ShouldBroadcastEvent (Event *ev
>>>              }
>>>          }
>>>      }
>>> +        break;
>>>  }
>>> -
>>> -    if (log)
>>> -        log->Printf ("Process::ShouldBroadcastEvent (%p) => %s - %s", event_ptr, StateAsCString(state), return_value ? "YES" : "NO");
>>> +
>>> +    // We do some coalescing of events (for instance two consecutive running events get coalesced.)
>>> +    // But we only coalesce against events we actually broadcast.  So we use m_last_broadcast_state
>>> +    // to track that.  NB - you can't use "m_public_state.GetValue()" for that purpose, as was originally done,
>>> +    // because the PublicState reflects the last event pulled off the queue, and there may be several
>>> +    // events stacked up on the queue unserviced.  So the PublicState may not reflect the last broadcasted event
>>> +    // yet.  m_last_broadcast_state gets updated here.
>>> +
>>> +    if (return_value)
>>> +        m_last_broadcast_state = state;
>>> +
>>> +    if (log)
>>> +        log->Printf ("Process::ShouldBroadcastEvent (%p) => new state: %s, last broadcast state: %s - %s",
>>> +                     event_ptr,
>>> +                     StateAsCString(state),
>>> +                     StateAsCString(m_last_broadcast_state),
>>> +                     return_value ? "YES" : "NO");
>>>  return return_value;
>>> }
>>> 
>>> @@ -3585,7 +3619,7 @@ Process::StopPrivateStateThread ()
>>>  {
>>>      LogSP log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
>>>      if (log)
>>> -            printf ("Went to stop the private state thread, but it was already invalid.");
>>> +            log->Printf ("Went to stop the private state thread, but it was already invalid.");
>>>  }
>>> }
>>> 
>>> @@ -3667,6 +3701,9 @@ Process::HandlePrivateEvent (EventSP &ev
>>>  if (m_next_event_action_ap.get() != NULL)
>>>  {
>>>      NextEventAction::EventActionResult action_result = m_next_event_action_ap->PerformAction(event_sp);
>>> +        if (log)
>>> +            log->Printf ("Ran next event action, result was %d.", action_result);
>>> +
>>>      switch (action_result)
>>>      {
>>>          case NextEventAction::eEventActionSuccess:
>>> @@ -3871,7 +3908,7 @@ Process::ProcessEventData::DoOnRemoval (
>>> 
>>>  if (m_update_state != 1)
>>>      return;
>>> -
>>> +
>>>  m_process_sp->SetPublicState (m_state);
>>> 
>>>  // If we're stopped and haven't restarted, then do the breakpoint commands here:
>>> @@ -3926,20 +3963,29 @@ Process::ProcessEventData::DoOnRemoval (
>>>          StopInfoSP stop_info_sp = thread_sp->GetStopInfo ();
>>>          if (stop_info_sp && stop_info_sp->IsValid())
>>>          {
>>> -                stop_info_sp->PerformAction(event_ptr);
>>> -                // The stop action might restart the target.  If it does, then we want to mark that in the
>>> -                // event so that whoever is receiving it will know to wait for the running event and reflect
>>> -                // that state appropriately.
>>> -                // We also need to stop processing actions, since they aren't expecting the target to be running.
>>> -
>>> -                // FIXME: we might have run.
>>> -                if (stop_info_sp->HasTargetRunSinceMe())
>>> +                bool this_thread_wants_to_stop;
>>> +                if (stop_info_sp->GetOverrideShouldStop())
>>>              {
>>> -                    SetRestarted (true);
>>> -                    break;
>>> +                    this_thread_wants_to_stop = stop_info_sp->GetOverriddenShouldStopValue();
>>> +                }
>>> +                else
>>> +                {
>>> +                    stop_info_sp->PerformAction(event_ptr);
>>> +                    // The stop action might restart the target.  If it does, then we want to mark that in the
>>> +                    // event so that whoever is receiving it will know to wait for the running event and reflect
>>> +                    // that state appropriately.
>>> +                    // We also need to stop processing actions, since they aren't expecting the target to be running.
>>> +
>>> +                    // FIXME: we might have run.
>>> +                    if (stop_info_sp->HasTargetRunSinceMe())
>>> +                    {
>>> +                        SetRestarted (true);
>>> +                        break;
>>> +                    }
>>> +
>>> +                    this_thread_wants_to_stop = stop_info_sp->ShouldStop(event_ptr);
>>>              }
>>> 
>>> -                bool this_thread_wants_to_stop = stop_info_sp->ShouldStop(event_ptr);
>>>              if (still_should_stop == false)
>>>                  still_should_stop = this_thread_wants_to_stop;
>>>          }
>>> @@ -3954,7 +4000,7 @@ Process::ProcessEventData::DoOnRemoval (
>>>              SetRestarted(true);
>>>              // Use the public resume method here, since this is just
>>>              // extending a public resume.
>>> -                m_process_sp->Resume();
>>> +                m_process_sp->PrivateResume();
>>>          }
>>>          else
>>>          {
>>> @@ -3965,7 +4011,6 @@ Process::ProcessEventData::DoOnRemoval (
>>>                  SetRestarted(true);
>>>          }
>>>      }
>>> -
>>>  }
>>> }
>>> 
>>> @@ -4028,6 +4073,34 @@ Process::ProcessEventData::SetRestartedI
>>>      data->SetRestarted(new_value);
>>> }
>>> 
>>> +size_t
>>> +Process::ProcessEventData::GetNumRestartedReasons(const Event *event_ptr)
>>> +{
>>> +    ProcessEventData *data = const_cast<ProcessEventData *>(GetEventDataFromEvent (event_ptr));
>>> +    if (data != NULL)
>>> +        return data->GetNumRestartedReasons();
>>> +    else
>>> +        return 0;
>>> +}
>>> +
>>> +const char *
>>> +Process::ProcessEventData::GetRestartedReasonAtIndex(const Event *event_ptr, size_t idx)
>>> +{
>>> +    ProcessEventData *data = const_cast<ProcessEventData *>(GetEventDataFromEvent (event_ptr));
>>> +    if (data != NULL)
>>> +        return data->GetRestartedReasonAtIndex(idx);
>>> +    else
>>> +        return NULL;
>>> +}
>>> +
>>> +void
>>> +Process::ProcessEventData::AddRestartedReason (Event *event_ptr, const char *reason)
>>> +{
>>> +    ProcessEventData *data = const_cast<ProcessEventData *>(GetEventDataFromEvent (event_ptr));
>>> +    if (data != NULL)
>>> +        data->AddRestartedReason(reason);
>>> +}
>>> +
>>> bool
>>> Process::ProcessEventData::GetInterruptedFromEvent (const Event *event_ptr)
>>> {
>>> @@ -4479,12 +4552,38 @@ Process::RunThreadPlan (ExecutionContext
>>>      TimeValue* timeout_ptr = NULL;
>>>      TimeValue real_timeout;
>>> 
>>> -        bool first_timeout = true;
>>> +        bool before_first_timeout = true;  // This is set to false the first time that we have to halt the target.
>>>      bool do_resume = true;
>>>      bool handle_running_event = true;
>>>      const uint64_t default_one_thread_timeout_usec = 250000;
>>> -        uint64_t computed_timeout = 0;
>>> 
>>> +        // This is just for accounting:
>>> +        uint32_t num_resumes = 0;
>>> +
>>> +        TimeValue one_thread_timeout = TimeValue::Now();
>>> +        TimeValue final_timeout = one_thread_timeout;
>>> +
>>> +        if (run_others)
>>> +        {
>>> +            // If we are running all threads then we take half the time to run all threads, bounded by
>>> +            // .25 sec.
>>> +            if (timeout_usec == 0)
>>> +                one_thread_timeout.OffsetWithMicroSeconds(default_one_thread_timeout_usec);
>>> +            else
>>> +            {
>>> +                uint64_t computed_timeout = computed_timeout = timeout_usec / 2;
>>> +                if (computed_timeout > default_one_thread_timeout_usec)
>>> +                    computed_timeout = default_one_thread_timeout_usec;
>>> +                one_thread_timeout.OffsetWithMicroSeconds(computed_timeout);
>>> +            }
>>> +            final_timeout.OffsetWithMicroSeconds (timeout_usec);
>>> +        }
>>> +        else
>>> +        {
>>> +            if (timeout_usec != 0)
>>> +                final_timeout.OffsetWithMicroSeconds(timeout_usec);
>>> +        }
>>> +
>>>      // This while loop must exit out the bottom, there's cleanup that we need to do when we are done.
>>>      // So don't call return anywhere within it.
>>> 
>>> @@ -4493,6 +4592,11 @@ Process::RunThreadPlan (ExecutionContext
>>>          // 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 (log)
>>> +                log->Printf ("Top of while loop: do_resume: %i handle_running_event: %i before_first_timeout: %i.",
>>> +                             do_resume,
>>> +                             handle_running_event,
>>> +                             before_first_timeout);
>>> 
>>>          if (do_resume || handle_running_event)
>>>          {
>>> @@ -4500,38 +4604,59 @@ Process::RunThreadPlan (ExecutionContext
>>> 
>>>              if (do_resume)
>>>              {
>>> +                    num_resumes++;
>>>                  Error resume_error = PrivateResume ();
>>>                  if (!resume_error.Success())
>>>                  {
>>> -                        errors.Printf("Error resuming inferior: \"%s\".\n", resume_error.AsCString());
>>> +                        errors.Printf("Error resuming inferior the %d time: \"%s\".\n",
>>> +                                      num_resumes,
>>> +                                      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);
>>> +                TimeValue resume_timeout = TimeValue::Now();
>>> +                resume_timeout.OffsetWithMicroSeconds(500000);
>>> +
>>> +                got_event = listener.WaitForEvent(&resume_timeout, event_sp);
>>>              if (!got_event)
>>>              {
>>>                  if (log)
>>> -                        log->PutCString("Process::RunThreadPlan(): didn't get any event after initial resume, exiting.");
>>> +                        log->Printf ("Process::RunThreadPlan(): didn't get any event after resume %d, exiting.",
>>> +                                        num_resumes);
>>> 
>>> -                    errors.Printf("Didn't get any event after initial resume, exiting.");
>>> +                    errors.Printf("Didn't get any event after resume %d, exiting.", num_resumes);
>>>                  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));
>>> -
>>> +                    bool restarted = false;
>>> +
>>> +                    if (stop_state == eStateStopped)
>>> +                    {
>>> +                        restarted = Process::ProcessEventData::GetRestartedFromEvent(event_sp.get());
>>> +                        if (log)
>>> +                            log->Printf("Process::RunThreadPlan(): didn't get running event after "
>>> +                                        "resume %d, got %s instead (restarted: %i, do_resume: %i, handle_running_event: %i).",
>>> +                                        num_resumes,
>>> +                                        StateAsCString(stop_state),
>>> +                                        restarted,
>>> +                                        do_resume,
>>> +                                        handle_running_event);
>>> +                    }
>>> +
>>> +                    if (restarted)
>>> +                    {
>>> +                        // This is probably an overabundance of caution, I don't think I should ever get a stopped & restarted
>>> +                        // event here.  But if I do, the best thing is to Halt and then get out of here.
>>> +                        Halt();
>>> +                    }
>>> +
>>>                  errors.Printf("Didn't get running event after initial resume, got %s instead.",
>>>                                StateAsCString(stop_state));
>>>                  return_value = eExecutionSetupError;
>>> @@ -4545,55 +4670,35 @@ Process::RunThreadPlan (ExecutionContext
>>>              // 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 (first_timeout)
>>> -                {
>>> -                    if (run_others)
>>> -                    {
>>> -                        // If we are running all threads then we take half the time to run all threads, bounded by
>>> -                        // .25 sec.
>>> -                        if (timeout_usec == 0)
>>> -                            computed_timeout = default_one_thread_timeout_usec;
>>> -                        else
>>> -                        {
>>> -                            computed_timeout = timeout_usec / 2;
>>> -                            if (computed_timeout > default_one_thread_timeout_usec)
>>> -                            {
>>> -                                computed_timeout = default_one_thread_timeout_usec;
>>> -                            }
>>> -                            timeout_usec -= computed_timeout;
>>> -                        }
>>> -                    }
>>> -                    else
>>> -                    {
>>> -                        computed_timeout = timeout_usec;
>>> -                    }
>>> -                }
>>> -                else
>>> -                {
>>> -                    computed_timeout = timeout_usec;
>>> -                }
>>> -
>>> -                if (computed_timeout != 0)
>>> -                {
>>> -                    // we have a > 0 timeout, let us set it so that we stop after the deadline
>>> -                    real_timeout = TimeValue::Now();
>>> -                    real_timeout.OffsetWithMicroSeconds(computed_timeout);
>>> +            }
>>> +            else
>>> +            {
>>> +                if (log)
>>> +                    log->PutCString ("Process::RunThreadPlan(): waiting for next event.");
>>> +            }
>>> 
>>> -                    timeout_ptr = &real_timeout;
>>> -                }
>>> +            if (before_first_timeout)
>>> +            {
>>> +                if (run_others)
>>> +                    timeout_ptr = &one_thread_timeout;
>>>              else
>>>              {
>>> -                    timeout_ptr = NULL;
>>> +                    if (timeout_usec == 0)
>>> +                        timeout_ptr = NULL;
>>> +                    else
>>> +                        timeout_ptr = &final_timeout;
>>>              }
>>>          }
>>>          else
>>>          {
>>> -                if (log)
>>> -                    log->PutCString ("Process::RunThreadPlan(): handled an extra running event.");
>>> -                do_resume = true;
>>> -                handle_running_event = true;
>>> +                if (timeout_usec == 0)
>>> +                    timeout_ptr = NULL;
>>> +                else
>>> +                    timeout_ptr = &final_timeout;
>>>          }
>>> +
>>> +            do_resume = true;
>>> +            handle_running_event = true;
>>> 
>>>          // Now wait for the process to stop again:
>>>          event_sp.reset();
>>> @@ -4602,12 +4707,9 @@ Process::RunThreadPlan (ExecutionContext
>>>          {
>>>              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());
>>> +                    log->Printf ("Process::RunThreadPlan(): about to wait - now is %llu - endpoint is %llu",
>>> +                                 TimeValue::Now().GetAsMicroSecondsSinceJan1_1970(),
>>> +                                 timeout_ptr->GetAsMicroSecondsSinceJan1_1970());
>>>              }
>>>              else
>>>              {
>>> @@ -4625,11 +4727,11 @@ Process::RunThreadPlan (ExecutionContext
>>>                  if (event_sp->GetType() == eBroadcastBitInterrupt)
>>>                  {
>>>                      Halt();
>>> -                        keep_going = false;
>>>                      return_value = eExecutionInterrupted;
>>>                      errors.Printf ("Execution halted by user interrupt.");
>>>                      if (log)
>>>                          log->Printf ("Process::RunThreadPlan(): Got  interrupted by eBroadcastBitInterrupted, exiting.");
>>> +                        break;
>>>                  }
>>>                  else
>>>                  {
>>> @@ -4641,7 +4743,7 @@ Process::RunThreadPlan (ExecutionContext
>>>                      {
>>>                      case lldb::eStateStopped:
>>>                          {
>>> -                                // Yay, we're done.  Now make sure that our thread plan actually completed.
>>> +                                // We stopped, figure out what we are going to do now.
>>>                              ThreadSP thread_sp = GetThreadList().FindThreadByIndexID (thread_idx_id);
>>>                              if (!thread_sp)
>>>                              {
>>> @@ -4652,52 +4754,63 @@ Process::RunThreadPlan (ExecutionContext
>>>                              }
>>>                              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)
>>> +                                    // If we were restarted, we just need to go back up to fetch another event.
>>> +                                    if (Process::ProcessEventData::GetRestartedFromEvent(event_sp.get()))
>>>                                  {
>>>                                      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(): Got a stop and restart, so we'll continue waiting.");
>>> +                                        }
>>> +                                       keep_going = true;
>>> +                                       do_resume = false;
>>> +                                       handle_running_event = true;
>>> +
>>>                                  }
>>>                                  else
>>>                                  {
>>> -                                        // Something restarted the target, so just wait for it to stop for real.
>>> -                                        if (Process::ProcessEventData::GetRestartedFromEvent(event_sp.get()))
>>> +
>>> +                                        StopInfoSP stop_info_sp (thread_sp->GetStopInfo ());
>>> +                                        StopReason stop_reason = eStopReasonInvalid;
>>> +                                        if (stop_info_sp)
>>> +                                             stop_reason = stop_info_sp->GetStopReason();
>>> +
>>> +
>>> +                                        // FIXME: We only check if the stop reason is plan complete, should we make sure that
>>> +                                        // it is OUR plan that is complete?
>>> +                                        if (stop_reason == eStopReasonPlanComplete)
>>>                                      {
>>>                                          if (log)
>>> -                                                log->PutCString ("Process::RunThreadPlan(): Somebody stopped and then restarted, we'll continue waiting.");
>>> -                                           keep_going = true;
>>> -                                           do_resume = false;
>>> -                                           handle_running_event = true;
>>> +                                                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.");
>>> +                                            // Something restarted the target, so just wait for it to stop for real.
>>>                                          if (stop_reason == eStopReasonBreakpoint)
>>> +                                            {
>>> +                                                if (log)
>>> +                                                    log->Printf ("Process::RunThreadPlan() stopped for breakpoint: %s.", stop_info_sp->GetDescription());
>>>                                              return_value = eExecutionHitBreakpoint;
>>> +                                            }
>>>                                          else
>>> +                                            {
>>> +                                                if (log)
>>> +                                                    log->PutCString ("Process::RunThreadPlan(): thread plan didn't successfully complete.");
>>>                                              return_value = eExecutionInterrupted;
>>> +                                            }
>>>                                      }
>>>                                  }
>>>                              }
>>>                          }
>>>                          break;
>>> 
>>> -                        case lldb::eStateCrashed:
>>> -                            if (log)
>>> -                                log->PutCString ("Process::RunThreadPlan(): execution crashed.");
>>> -                            return_value = eExecutionInterrupted;
>>> -                            break;
>>> -
>>>                      case lldb::eStateRunning:
>>> +                            // This shouldn't really happen, but sometimes we do get two running events without an
>>> +                            // intervening stop, and in that case we should just go back to waiting for the stop.
>>>                          do_resume = false;
>>>                          keep_going = true;
>>>                          handle_running_event = false;
>>> @@ -4734,15 +4847,15 @@ Process::RunThreadPlan (ExecutionContext
>>>              // 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 (run_others)
>>>                  {
>>> -                        if (first_timeout)
>>> -                            log->Printf ("Process::RunThreadPlan(): Running function with timeout: %" PRId64 " timed out, "
>>> -                                         "trying  for %d usec with all threads enabled.",
>>> -                                         computed_timeout, timeout_usec);
>>> +                        uint64_t remaining_time = final_timeout - TimeValue::Now();
>>> +                        if (before_first_timeout)
>>> +                            log->Printf ("Process::RunThreadPlan(): Running function with one thread timeout timed out, "
>>> +                                         "running till  for %" PRId64 " usec with all threads enabled.",
>>> +                                         remaining_time);
>>>                      else
>>>                          log->Printf ("Process::RunThreadPlan(): Restarting function with all threads enabled "
>>>                                       "and timeout: %d timed out, abandoning execution.",
>>> @@ -4754,148 +4867,122 @@ Process::RunThreadPlan (ExecutionContext
>>>                                   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)
>>> -                    {
>>> -                        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:
>>> -
>>> -                            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 (!run_others)
>>> -                            {
>>> -                                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
>>> +                // It is possible that between the time we issued the Halt, and we get around to calling Halt the target
>>> +                // could have stopped.  That's fine, Halt will figure that out and send the appropriate Stopped event.
>>> +                // BUT it is also possible that we stopped & restarted (e.g. hit a signal with "stop" set to false.)  In
>>> +                // that case, we'll get the stopped & restarted event, and we should go back to waiting for the Halt's
>>> +                // stopped event.  That's what this while loop does.
>>> +
>>> +                bool back_to_top = true;
>>> +                uint32_t try_halt_again = 0;
>>> +                bool do_halt = true;
>>> +                const uint32_t num_retries = 5;
>>> +                while (try_halt_again < num_retries)
>>>              {
>>> -                    // 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)
>>> +                    Error halt_error;
>>> +                    if (do_halt)
>>>                  {
>>> -                        // 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;
>>> +                            log->Printf ("Process::RunThreadPlan(): Running Halt.");
>>> +                        halt_error = Halt();
>>>                  }
>>> -                    else
>>> +                    if (halt_error.Success())
>>>                  {
>>> -                        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)
>>> -                        {
>>> -                            // 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;
>>> -                            }
>>> +                        real_timeout = TimeValue::Now();
>>> +                        real_timeout.OffsetWithMicroSeconds(500000);
>>> 
>>> -                            if (first_timeout)
>>> +                        got_event = listener.WaitForEvent(&real_timeout, event_sp);
>>> +
>>> +                        if (got_event)
>>> +                        {
>>> +                            stop_state = Process::ProcessEventData::GetStateFromEvent(event_sp.get());
>>> +                            if (log)
>>>                          {
>>> -                                // 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;
>>> +                                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.");
>>>                          }
>>> -                            else
>>> +
>>> +                            if (stop_state == lldb::eStateStopped)
>>>                          {
>>> -                                // Running all threads failed, so return Interrupted.
>>> -                                if (log)
>>> -                                    log->PutCString ("Process::RunThreadPlan(): running all threads timed out.");
>>> -                                return_value = eExecutionInterrupted;
>>> -                                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;
>>> +                                    back_to_top = false;
>>> +                                    break;
>>> +                                }
>>> +
>>> +                                if (Process::ProcessEventData::GetRestartedFromEvent(event_sp.get()))
>>> +                                {
>>> +                                    if (log)
>>> +                                        log->PutCString ("Process::RunThreadPlan(): Went to halt but got a restarted event, there must be an un-restarted stopped event so try again...  "
>>> +                                                     "Exiting wait loop.");
>>> +                                    try_halt_again++;
>>> +                                    do_halt = false;
>>> +                                    continue;
>>> +                                }
>>> +
>>> +                                if (!run_others)
>>> +                                {
>>> +                                    if (log)
>>> +                                        log->PutCString ("Process::RunThreadPlan(): try_all_threads was false, we stopped so now we're quitting.");
>>> +                                    return_value = eExecutionInterrupted;
>>> +                                    back_to_top = false;
>>> +                                    break;
>>> +                                }
>>> +
>>> +                                if (before_first_timeout)
>>> +                                {
>>> +                                    // Set all the other threads to run, and return to the top of the loop, which will continue;
>>> +                                    before_first_timeout = false;
>>> +                                    thread_plan_sp->SetStopOthers (false);
>>> +                                    if (log)
>>> +                                        log->PutCString ("Process::RunThreadPlan(): about to resume.");
>>> +
>>> +                                    back_to_top = true;
>>> +                                    break;
>>> +                                }
>>> +                                else
>>> +                                {
>>> +                                    // Running all threads failed, so return Interrupted.
>>> +                                    if (log)
>>> +                                        log->PutCString("Process::RunThreadPlan(): running all threads timed out.");
>>> +                                    return_value = eExecutionInterrupted;
>>> +                                    back_to_top = false;
>>> +                                    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));
>>> +                        {   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;
>>> +                            back_to_top = false;
>>> +                            break;
>>>                      }
>>>                  }
>>> +                    else
>>> +                    {
>>> +                        try_halt_again++;
>>> +                        continue;
>>> +                    }
>>>              }
>>> -
>>> +
>>> +                if (!back_to_top || try_halt_again > num_retries)
>>> +                    break;
>>> +                else
>>> +                    continue;
>>>          }
>>>      }  // END WAIT LOOP
>>> 
>>> 
>>> Modified: lldb/trunk/source/Target/StopInfo.cpp
>>> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/StopInfo.cpp?rev=174793&r1=174792&r2=174793&view=diff
>>> ==============================================================================
>>> --- lldb/trunk/source/Target/StopInfo.cpp (original)
>>> +++ lldb/trunk/source/Target/StopInfo.cpp Fri Feb  8 19:29:05 2013
>>> @@ -38,7 +38,9 @@ StopInfo::StopInfo (Thread &thread, uint
>>>  m_thread (thread),
>>>  m_stop_id (thread.GetProcess()->GetStopID()),
>>>  m_resume_id (thread.GetProcess()->GetResumeID()),
>>> -    m_value (value)
>>> +    m_value (value),
>>> +    m_override_set(false),
>>> +    m_override_value(true)
>>> {
>>> }
>>> 
>>> @@ -773,6 +775,12 @@ public:
>>>  }
>>> 
>>>  virtual bool
>>> +    ShouldStopSynchronous (Event *event_ptr)
>>> +    {
>>> +        return m_thread.GetProcess()->GetUnixSignals().GetShouldStop (m_value);
>>> +    }
>>> +
>>> +    virtual bool
>>>  ShouldStop (Event *event_ptr)
>>>  {
>>>      return m_thread.GetProcess()->GetUnixSignals().GetShouldStop (m_value);
>>> @@ -783,7 +791,16 @@ public:
>>>  virtual bool
>>>  ShouldNotify (Event *event_ptr)
>>>  {
>>> -        return m_thread.GetProcess()->GetUnixSignals().GetShouldNotify (m_value);
>>> +        bool should_notify = m_thread.GetProcess()->GetUnixSignals().GetShouldNotify (m_value);
>>> +        if (should_notify)
>>> +        {
>>> +            StreamString strm;
>>> +            strm.Printf ("thread %d received signal: %s",
>>> +                         m_thread.GetIndexID(),
>>> +                         m_thread.GetProcess()->GetUnixSignals().GetSignalAsCString (m_value));
>>> +            Process::ProcessEventData::AddRestartedReason(event_ptr, strm.GetData());
>>> +        }
>>> +        return should_notify;
>>>  }
>>> 
>>> 
>>> @@ -924,6 +941,16 @@ public:
>>>  {
>>>      return m_return_valobj_sp;
>>>  }
>>> +
>>> +protected:
>>> +    virtual bool
>>> +    ShouldStop (Event *event_ptr)
>>> +    {
>>> +        if (m_plan_sp)
>>> +            return m_plan_sp->ShouldStop(event_ptr);
>>> +        else
>>> +            return StopInfo::ShouldStop(event_ptr);
>>> +    }
>>> 
>>> private:
>>>  ThreadPlanSP m_plan_sp;
>>> @@ -957,7 +984,6 @@ public:
>>>      return "exec";
>>>  }
>>> protected:
>>> -protected:
>>> 
>>>  virtual void
>>>  PerformAction (Event *event_ptr)
>>> 
>>> Modified: lldb/trunk/source/Target/Thread.cpp
>>> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/Thread.cpp?rev=174793&r1=174792&r2=174793&view=diff
>>> ==============================================================================
>>> --- lldb/trunk/source/Target/Thread.cpp (original)
>>> +++ lldb/trunk/source/Target/Thread.cpp Fri Feb  8 19:29:05 2013
>>> @@ -646,7 +646,7 @@ Thread::ShouldStop (Event* event_ptr)
>>> 
>>>  bool done_processing_current_plan = false;
>>> 
>>> -    if (!current_plan->PlanExplainsStop())
>>> +    if (!current_plan->PlanExplainsStop(event_ptr))
>>>  {
>>>      if (current_plan->TracerExplainsStop())
>>>      {
>>> @@ -660,7 +660,7 @@ Thread::ShouldStop (Event* event_ptr)
>>>          ThreadPlan *plan_ptr = current_plan;
>>>          while ((plan_ptr = GetPreviousPlan(plan_ptr)) != NULL)
>>>          {
>>> -                if (plan_ptr->PlanExplainsStop())
>>> +                if (plan_ptr->PlanExplainsStop(event_ptr))
>>>              {
>>>                  should_stop = plan_ptr->ShouldStop (event_ptr);
>>> 
>>> @@ -831,9 +831,24 @@ Thread::ShouldReportStop (Event* event_p
>>>  }
>>>  else
>>>  {
>>> +        Vote thread_vote = eVoteNoOpinion;
>>> +        ThreadPlan *plan_ptr = GetCurrentPlan();
>>> +        while (1)
>>> +        {
>>> +            if (plan_ptr->PlanExplainsStop(event_ptr))
>>> +            {
>>> +                thread_vote = plan_ptr->ShouldReportStop(event_ptr);
>>> +                break;
>>> +            }
>>> +            if (PlanIsBasePlan(plan_ptr))
>>> +                break;
>>> +            else
>>> +                plan_ptr = GetPreviousPlan(plan_ptr);
>>> +        }
>>>      if (log)
>>> -            log->Printf ("Thread::ShouldReportStop() tid = 0x%4.4" PRIx64 ": returning vote  for current plan\n", GetID());
>>> -        return GetCurrentPlan()->ShouldReportStop (event_ptr);
>>> +            log->Printf ("Thread::ShouldReportStop() tid = 0x%4.4" PRIx64 ": returning vote %i for current plan\n", GetID(), thread_vote);
>>> +
>>> +        return thread_vote;
>>>  }
>>> }
>>> 
>>> 
>>> Modified: lldb/trunk/source/Target/ThreadPlanBase.cpp
>>> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/ThreadPlanBase.cpp?rev=174793&r1=174792&r2=174793&view=diff
>>> ==============================================================================
>>> --- lldb/trunk/source/Target/ThreadPlanBase.cpp (original)
>>> +++ lldb/trunk/source/Target/ThreadPlanBase.cpp Fri Feb  8 19:29:05 2013
>>> @@ -68,7 +68,7 @@ ThreadPlanBase::ValidatePlan (Stream *er
>>> }
>>> 
>>> bool
>>> -ThreadPlanBase::PlanExplainsStop ()
>>> +ThreadPlanBase::PlanExplainsStop (Event *event_ptr)
>>> {
>>>  // The base plan should defer to its tracer, since by default it
>>>  // always handles the stop.
>>> 
>>> Modified: lldb/trunk/source/Target/ThreadPlanCallFunction.cpp
>>> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/ThreadPlanCallFunction.cpp?rev=174793&r1=174792&r2=174793&view=diff
>>> ==============================================================================
>>> --- lldb/trunk/source/Target/ThreadPlanCallFunction.cpp (original)
>>> +++ lldb/trunk/source/Target/ThreadPlanCallFunction.cpp Fri Feb  8 19:29:05 2013
>>> @@ -231,7 +231,7 @@ ThreadPlanCallFunction::ThreadPlanCallFu
>>> 
>>> ThreadPlanCallFunction::~ThreadPlanCallFunction ()
>>> {
>>> -    DoTakedown(true);
>>> +    DoTakedown(PlanSucceeded());
>>> }
>>> 
>>> void
>>> @@ -309,7 +309,7 @@ ThreadPlanCallFunction::DoTakedown (bool
>>> void
>>> ThreadPlanCallFunction::WillPop ()
>>> {
>>> -    DoTakedown(true);
>>> +    DoTakedown(PlanSucceeded());
>>> }
>>> 
>>> void
>>> @@ -335,14 +335,25 @@ ThreadPlanCallFunction::ValidatePlan (St
>>>  return true;
>>> }
>>> 
>>> +
>>> +Vote
>>> +ThreadPlanCallFunction::ShouldReportStop(Event *event_ptr)
>>> +{
>>> +    if (m_takedown_done || IsPlanComplete())
>>> +        return eVoteYes;
>>> +    else
>>> +        return ThreadPlan::ShouldReportStop(event_ptr);
>>> +}
>>> +
>>> bool
>>> -ThreadPlanCallFunction::PlanExplainsStop ()
>>> +ThreadPlanCallFunction::PlanExplainsStop (Event *event_ptr)
>>> {
>>> +    LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_STEP|LIBLLDB_LOG_PROCESS));
>>>  m_real_stop_info_sp = GetPrivateStopReason();
>>> 
>>>  // If our subplan knows why we stopped, even if it's done (which would forward the question to us)
>>>  // we answer yes.
>>> -    if (m_subplan_sp.get() != NULL && m_subplan_sp->PlanExplainsStop())
>>> +    if (m_subplan_sp.get() != NULL && m_subplan_sp->PlanExplainsStop(event_ptr))
>>>  {
>>>      SetPlanComplete();
>>>      return true;
>>> @@ -355,16 +366,15 @@ ThreadPlanCallFunction::PlanExplainsStop
>>>      stop_reason = eStopReasonNone;
>>>  else
>>>      stop_reason = m_real_stop_info_sp->GetStopReason();
>>> +    if (log)
>>> +        log->Printf ("ThreadPlanCallFunction::PlanExplainsStop: Got stop reason - %s.", Thread::StopReasonAsCString(stop_reason));
>>> 
>>>  if (stop_reason == eStopReasonBreakpoint && BreakpointsExplainStop())
>>>      return true;
>>> 
>>> -    // If we don't want to discard this plan, than any stop we don't understand should be propagated up the stack.
>>> -    if (!m_unwind_on_error)
>>> -        return false;
>>> -
>>> -    // Otherwise, check the case where we stopped for an internal breakpoint, in that case, continue on.
>>> -    // If it is not an internal breakpoint, consult OkayToDiscard.
>>> +    // We control breakpoints separately from other "stop reasons."  So first,
>>> +    // check the case where we stopped for an internal breakpoint, in that case, continue on.
>>> +    // If it is not an internal breakpoint, consult m_ignore_breakpoints.
>>> 
>>> 
>>>  if (stop_reason == eStopReasonBreakpoint)
>>> @@ -381,6 +391,8 @@ ThreadPlanCallFunction::PlanExplainsStop
>>>          for (uint32_t i = 0; i < num_owners; i++)
>>>          {
>>>              Breakpoint &bp = bp_site_sp->GetOwnerAtIndex(i)->GetBreakpoint();
>>> +                if (log)
>>> +                    log->Printf ("ThreadPlanCallFunction::PlanExplainsStop: hit breakpoint %d while calling function", bp.GetID());
>>> 
>>>              if (!bp.IsInternal())
>>>              {
>>> @@ -389,16 +401,32 @@ ThreadPlanCallFunction::PlanExplainsStop
>>>              }
>>>          }
>>>          if (is_internal)
>>> +            {
>>> +                if (log)
>>> +                    log->Printf ("ThreadPlanCallFunction::PlanExplainsStop hit an internal breakpoint, not stopping.");
>>>              return false;
>>> +            }
>>>      }
>>> -
>>> +
>>>      if (m_ignore_breakpoints)
>>>      {
>>> -            DoTakedown(false);
>>> +            if (log)
>>> +                log->Printf("ThreadPlanCallFunction::PlanExplainsStop: we are ignoring breakpoints, overriding breakpoint stop info ShouldStop, returning true");
>>> +            m_real_stop_info_sp->OverrideShouldStop(false);
>>>          return true;
>>>      }
>>>      else
>>> +        {
>>> +            if (log)
>>> +                log->Printf("ThreadPlanCallFunction::PlanExplainsStop: we are not ignoring breakpoints, overriding breakpoint stop info ShouldStop, returning true");
>>> +            m_real_stop_info_sp->OverrideShouldStop(true);
>>>          return false;
>>> +        }
>>> +    }
>>> +    else if (!m_unwind_on_error)
>>> +    {
>>> +        // If we don't want to discard this plan, than any stop we don't understand should be propagated up the stack.
>>> +        return false;
>>>  }
>>>  else
>>>  {
>>> @@ -406,19 +434,25 @@ ThreadPlanCallFunction::PlanExplainsStop
>>>      // If we want to discard the plan, then we say we explain the stop
>>>      // but if we are going to be discarded, let whoever is above us
>>>      // explain the stop.
>>> -        SetPlanComplete(false);
>>> -        if (m_subplan_sp)
>>> +        // But don't discard the plan if the stop would restart itself (for instance if it is a
>>> +        // signal that is set not to stop.  Check that here first.  We just say we explain the stop
>>> +        // but aren't done and everything will continue on from there.
>>> +
>>> +        if (m_real_stop_info_sp->ShouldStopSynchronous(event_ptr))
>>>      {
>>> -            if (m_unwind_on_error)
>>> +            SetPlanComplete(false);
>>> +            if (m_subplan_sp)
>>>          {
>>> -                DoTakedown(false);
>>> -                return true;
>>> +                if (m_unwind_on_error)
>>> +                    return true;
>>> +                else
>>> +                    return false;
>>>          }
>>>          else
>>>              return false;
>>>      }
>>>      else
>>> -            return false;
>>> +            return true;
>>>  }
>>> }
>>> 
>>> @@ -427,14 +461,11 @@ ThreadPlanCallFunction::ShouldStop (Even
>>> {
>>>  // We do some computation in PlanExplainsStop that may or may not set the plan as complete.
>>>  // We need to do that here to make sure our state is correct.
>>> -    PlanExplainsStop();
>>> +    PlanExplainsStop(event_ptr);
>>> 
>>>  if (IsPlanComplete())
>>>  {
>>>      ReportRegisterState ("Function completed.  Register state was:");
>>> -
>>> -        DoTakedown(true);
>>> -
>>>      return true;
>>>  }
>>>  else
>>> @@ -495,12 +526,6 @@ ThreadPlanCallFunction::MischiefManaged
>>> {
>>>  LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
>>> 
>>> -    if (PlanExplainsStop() && !IsPlanComplete())
>>> -    {
>>> -        if (log)
>>> -            log->Printf ("ThreadPlanCallFunction: Got into MischiefManaged, explained stop but was not complete.");
>>> -    }
>>> -
>>>  if (IsPlanComplete())
>>>  {
>>>      if (log)
>>> 
>>> Modified: lldb/trunk/source/Target/ThreadPlanRunToAddress.cpp
>>> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/ThreadPlanRunToAddress.cpp?rev=174793&r1=174792&r2=174793&view=diff
>>> ==============================================================================
>>> --- lldb/trunk/source/Target/ThreadPlanRunToAddress.cpp (original)
>>> +++ lldb/trunk/source/Target/ThreadPlanRunToAddress.cpp Fri Feb  8 19:29:05 2013
>>> @@ -188,7 +188,7 @@ ThreadPlanRunToAddress::ValidatePlan (St
>>> }
>>> 
>>> bool
>>> -ThreadPlanRunToAddress::PlanExplainsStop ()
>>> +ThreadPlanRunToAddress::PlanExplainsStop (Event *event_ptr)
>>> {
>>>  return AtOurAddress();
>>> }
>>> 
>>> Modified: lldb/trunk/source/Target/ThreadPlanStepInRange.cpp
>>> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/ThreadPlanStepInRange.cpp?rev=174793&r1=174792&r2=174793&view=diff
>>> ==============================================================================
>>> --- lldb/trunk/source/Target/ThreadPlanStepInRange.cpp (original)
>>> +++ lldb/trunk/source/Target/ThreadPlanStepInRange.cpp Fri Feb  8 19:29:05 2013
>>> @@ -351,7 +351,7 @@ ThreadPlanStepInRange::DefaultShouldStop
>>> }
>>> 
>>> bool
>>> -ThreadPlanStepInRange::PlanExplainsStop ()
>>> +ThreadPlanStepInRange::PlanExplainsStop (Event *event_ptr)
>>> {
>>>  // We always explain a stop.  Either we've just done a single step, in which
>>>  // case we'll do our ordinary processing, or we stopped for some
>>> 
>>> Modified: lldb/trunk/source/Target/ThreadPlanStepInstruction.cpp
>>> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/ThreadPlanStepInstruction.cpp?rev=174793&r1=174792&r2=174793&view=diff
>>> ==============================================================================
>>> --- lldb/trunk/source/Target/ThreadPlanStepInstruction.cpp (original)
>>> +++ lldb/trunk/source/Target/ThreadPlanStepInstruction.cpp Fri Feb  8 19:29:05 2013
>>> @@ -81,7 +81,7 @@ ThreadPlanStepInstruction::ValidatePlan
>>> }
>>> 
>>> bool
>>> -ThreadPlanStepInstruction::PlanExplainsStop ()
>>> +ThreadPlanStepInstruction::PlanExplainsStop (Event *event_ptr)
>>> {
>>>  StopInfoSP stop_info_sp = GetPrivateStopReason();
>>>  if (stop_info_sp)
>>> 
>>> Modified: lldb/trunk/source/Target/ThreadPlanStepOut.cpp
>>> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/ThreadPlanStepOut.cpp?rev=174793&r1=174792&r2=174793&view=diff
>>> ==============================================================================
>>> --- lldb/trunk/source/Target/ThreadPlanStepOut.cpp (original)
>>> +++ lldb/trunk/source/Target/ThreadPlanStepOut.cpp Fri Feb  8 19:29:05 2013
>>> @@ -174,7 +174,7 @@ ThreadPlanStepOut::ValidatePlan (Stream
>>> }
>>> 
>>> bool
>>> -ThreadPlanStepOut::PlanExplainsStop ()
>>> +ThreadPlanStepOut::PlanExplainsStop (Event *event_ptr)
>>> {
>>>  // If one of our child plans just finished, then we do explain the stop.
>>>  if (m_step_out_plan_sp)
>>> 
>>> Modified: lldb/trunk/source/Target/ThreadPlanStepOverBreakpoint.cpp
>>> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/ThreadPlanStepOverBreakpoint.cpp?rev=174793&r1=174792&r2=174793&view=diff
>>> ==============================================================================
>>> --- lldb/trunk/source/Target/ThreadPlanStepOverBreakpoint.cpp (original)
>>> +++ lldb/trunk/source/Target/ThreadPlanStepOverBreakpoint.cpp Fri Feb  8 19:29:05 2013
>>> @@ -58,7 +58,7 @@ ThreadPlanStepOverBreakpoint::ValidatePl
>>> }
>>> 
>>> bool
>>> -ThreadPlanStepOverBreakpoint::PlanExplainsStop ()
>>> +ThreadPlanStepOverBreakpoint::PlanExplainsStop (Event *event_ptr)
>>> {
>>>  StopInfoSP stop_info_sp = GetPrivateStopReason();
>>>  if (stop_info_sp)
>>> 
>>> Modified: lldb/trunk/source/Target/ThreadPlanStepOverRange.cpp
>>> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/ThreadPlanStepOverRange.cpp?rev=174793&r1=174792&r2=174793&view=diff
>>> ==============================================================================
>>> --- lldb/trunk/source/Target/ThreadPlanStepOverRange.cpp (original)
>>> +++ lldb/trunk/source/Target/ThreadPlanStepOverRange.cpp Fri Feb  8 19:29:05 2013
>>> @@ -290,7 +290,7 @@ ThreadPlanStepOverRange::ShouldStop (Eve
>>> }
>>> 
>>> bool
>>> -ThreadPlanStepOverRange::PlanExplainsStop ()
>>> +ThreadPlanStepOverRange::PlanExplainsStop (Event *event_ptr)
>>> {
>>>  // For crashes, breakpoint hits, signals, etc, let the base plan (or some plan above us)
>>>  // handle the stop.  That way the user can see the stop, step around, and then when they
>>> 
>>> Modified: lldb/trunk/source/Target/ThreadPlanStepThrough.cpp
>>> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/ThreadPlanStepThrough.cpp?rev=174793&r1=174792&r2=174793&view=diff
>>> ==============================================================================
>>> --- lldb/trunk/source/Target/ThreadPlanStepThrough.cpp (original)
>>> +++ lldb/trunk/source/Target/ThreadPlanStepThrough.cpp Fri Feb  8 19:29:05 2013
>>> @@ -139,7 +139,7 @@ ThreadPlanStepThrough::ValidatePlan (Str
>>> }
>>> 
>>> bool
>>> -ThreadPlanStepThrough::PlanExplainsStop ()
>>> +ThreadPlanStepThrough::PlanExplainsStop (Event *event_ptr)
>>> {
>>>  // If we have a sub-plan, it will have been asked first if we explain the stop, and
>>>  // we won't get asked.  The only time we would be the one directly asked this question
>>> 
>>> Modified: lldb/trunk/source/Target/ThreadPlanStepUntil.cpp
>>> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/ThreadPlanStepUntil.cpp?rev=174793&r1=174792&r2=174793&view=diff
>>> ==============================================================================
>>> --- lldb/trunk/source/Target/ThreadPlanStepUntil.cpp (original)
>>> +++ lldb/trunk/source/Target/ThreadPlanStepUntil.cpp Fri Feb  8 19:29:05 2013
>>> @@ -305,7 +305,7 @@ ThreadPlanStepUntil::AnalyzeStop()
>>> }
>>> 
>>> bool
>>> -ThreadPlanStepUntil::PlanExplainsStop ()
>>> +ThreadPlanStepUntil::PlanExplainsStop (Event *event_ptr)
>>> {
>>>  // We don't explain signals or breakpoints (breakpoints that handle stepping in or
>>>  // out will be handled by a child plan.
>>> 
>>> Modified: lldb/trunk/test/functionalities/conditional_break/conditional_break.py
>>> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/conditional_break/conditional_break.py?rev=174793&r1=174792&r2=174793&view=diff
>>> ==============================================================================
>>> --- lldb/trunk/test/functionalities/conditional_break/conditional_break.py (original)
>>> +++ lldb/trunk/test/functionalities/conditional_break/conditional_break.py Fri Feb  8 19:29:05 2013
>>> @@ -32,6 +32,7 @@ def stop_if_called_from_a():
>>>          should_stop = False
>>> 
>>>  dbg.SetAsync(old_async)
>>> +    print >> sys.stdout, "stop_if_called_from_a returning: ", should_stop
>>>  return should_stop
>>> 
>>> 
>>> 
>>> Modified: lldb/trunk/tools/driver/Driver.cpp
>>> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/driver/Driver.cpp?rev=174793&r1=174792&r2=174793&view=diff
>>> ==============================================================================
>>> --- lldb/trunk/tools/driver/Driver.cpp (original)
>>> +++ lldb/trunk/tools/driver/Driver.cpp Fri Feb  8 19:29:05 2013
>>> @@ -973,11 +973,32 @@ Driver::HandleProcessEvent (const SBEven
>>>          // Make sure the program hasn't been auto-restarted:
>>>          if (SBProcess::GetRestartedFromEvent (event))
>>>          {
>>> +                size_t num_reasons = SBProcess::GetNumRestartedReasonsFromEvent(event);
>>> +                if (num_reasons > 0)
>>> +                {
>>>              // FIXME: Do we want to report this, or would that just be annoyingly chatty?
>>> -                char message[1024];
>>> -                int message_len = ::snprintf (message, sizeof(message), "Process %" PRIu64 " stopped and was programmatically restarted.\n",
>>> +                    if (num_reasons == 1)
>>> +                    {
>>> +                        char message[1024];
>>> +                        const char *reason = SBProcess::GetRestartedReasonAtIndexFromEvent (event, 0);
>>> +                        int message_len = ::snprintf (message, sizeof(message), "Process %" PRIu64 " stopped and restarted: %s\n",
>>> +                                              process.GetProcessID(), reason ? reason : "<UNKNOWN REASON>");
>>> +                        m_io_channel_ap->OutWrite(message, message_len, ASYNC);
>>> +                    }
>>> +                    else
>>> +                    {
>>> +                        char message[1024];
>>> +                        int message_len = ::snprintf (message, sizeof(message), "Process %" PRIu64 " stopped and restarted, reasons:\n",
>>>                                            process.GetProcessID());
>>> -                m_io_channel_ap->OutWrite(message, message_len, ASYNC);
>>> +                        m_io_channel_ap->OutWrite(message, message_len, ASYNC);
>>> +                        for (size_t i = 0; i < num_reasons; i++)
>>> +                        {
>>> +                            const char *reason = SBProcess::GetRestartedReasonAtIndexFromEvent (event, i);
>>> +                            int message_len = ::snprintf(message, sizeof(message), "\t%s\n", reason ? reason : "<UNKNOWN REASON>");
>>> +                            m_io_channel_ap->OutWrite(message, message_len, ASYNC);
>>> +                        }
>>> +                    }
>>> +                }
>>>          }
>>>          else
>>>          {
>>> 
>>> 
>>> _______________________________________________
>>> lldb-commits mailing list
>>> lldb-commits at cs.uiuc.edu<mailto:lldb-commits at cs.uiuc.edu>
>>> http://lists.cs.uiuc.edu/mailman/listinfo/lldb-commits
>>> 
>> 
> 





More information about the lldb-commits mailing list