Figure out the reply to "PlanExplainsStop" once when we stop and then use the cached

value.  This fixes problems, for instance, with the StepRange plans, where they know that
they explained the stop because they were at their "run to here" breakpoint, then deleted
that breakpoint, so when they got asked again, doh!  I had done this for a couple of plans
in an ad hoc fashion, this just formalizes it.

Also add a "ResumeRequested" in Process so that the code in the completion handlers can
tell the ShouldStop logic they want to resume rather than just directly resuming.  That allows 
us to handle resuming in a more controlled fashion.

Also, SetPublicState can take a "restarted" flag, so that it doesn't drop the run lock when
the target was immediately restarted.
--This line, and those below , will be ignored--

M    test/lang/objc/objc-dynamic-value/TestObjCDynamicValue.py
M    include/lldb/Target/ThreadList.h
M    include/lldb/Target/ThreadPlanStepOut.h
M    include/lldb/Target/Thread.h
M    include/lldb/Target/ThreadPlanBase.h
M    include/lldb/Target/ThreadPlanStepThrough.h
M    include/lldb/Target/ThreadPlanStepInstruction.h
M    include/lldb/Target/ThreadPlanStepInRange.h
M    include/lldb/Target/ThreadPlanStepOverBreakpoint.h
M    include/lldb/Target/ThreadPlanStepUntil.h
M    include/lldb/Target/StopInfo.h
M    include/lldb/Target/Process.h
M    include/lldb/Target/ThreadPlanRunToAddress.h
M    include/lldb/Target/ThreadPlan.h
M    include/lldb/Target/ThreadPlanCallFunction.h
M    include/lldb/Target/ThreadPlanStepOverRange.h
M    source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.h
M    source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp
M    source/Target/StopInfo.cpp
M    source/Target/Process.cpp
M    source/Target/ThreadPlanRunToAddress.cpp
M    source/Target/ThreadPlan.cpp
M    source/Target/ThreadPlanCallFunction.cpp
M    source/Target/ThreadPlanStepOverRange.cpp
M    source/Target/ThreadList.cpp
M    source/Target/ThreadPlanStepOut.cpp
M    source/Target/Thread.cpp
M    source/Target/ThreadPlanBase.cpp
M    source/Target/ThreadPlanStepThrough.cpp
M    source/Target/ThreadPlanStepInstruction.cpp
M    source/Target/ThreadPlanStepInRange.cpp
M    source/Target/ThreadPlanStepOverBreakpoint.cpp
M    source/Target/ThreadPlanStepUntil.cpp
M    lldb.xcodeproj/xcshareddata/xcschemes/Run Testsuite.xcscheme

llvm-svn: 181381
This commit is contained in:
Jim Ingham 2013-05-08 00:35:16 +00:00
parent 6156011ee8
commit 221d51cf84
34 changed files with 285 additions and 133 deletions

View File

@ -3348,13 +3348,15 @@ public:
void
RestoreProcessEvents ();
protected:
private:
//------------------------------------------------------------------
/// This is the part of the event handling that for a process event.
/// It decides what to do with the event and returns true if the
/// event needs to be propagated to the user, and false otherwise.
/// If the event is not propagated, this call will most likely set
/// the target to executing again.
/// There is only one place where this call should be called, HandlePrivateEvent.
/// Don't call it from anywhere else...
///
/// @param[in] event_ptr
/// This is the event we are handling.
@ -3526,6 +3528,9 @@ protected:
// new "NextEventAction" is added while one is already present, the
// old action will be discarded (with HandleBeingUnshipped called
// after it is discarded.)
//
// If you want to resume the process as a result of a resume action,
// call RequestResume, don't call Resume directly.
//------------------------------------------------------------------
class NextEventAction
{
@ -3551,6 +3556,10 @@ protected:
virtual void HandleBeingUnshipped () {}
virtual EventActionResult HandleBeingInterrupted () = 0;
virtual const char *GetExitString() = 0;
void RequestResume()
{
m_process->m_resume_requested = true;
}
protected:
Process *m_process;
};
@ -3661,7 +3670,9 @@ protected:
#if defined(__APPLE__)
ReadWriteLock m_private_run_lock;
#endif
Predicate<bool> m_currently_handling_event;
Predicate<bool> m_currently_handling_event; // This predicate is set in HandlePrivateEvent while all its business is being done.
bool m_currently_handling_do_on_removals;
bool m_resume_requested; // If m_currently_handling_event or m_currently_handling_do_on_removals are true, Resume will only request a resume, using this flag to check.
bool m_finalize_called;
lldb::StateType m_last_broadcast_state; /// This helps with the Public event coalescing in ShouldBroadcastEvent.
bool m_destroy_in_process;
@ -3679,7 +3690,7 @@ protected:
SynchronouslyNotifyStateChanged (lldb::StateType state);
void
SetPublicState (lldb::StateType new_state);
SetPublicState (lldb::StateType new_state, bool restarted);
void
SetPrivateState (lldb::StateType state);

View File

@ -79,11 +79,20 @@ public:
return true;
}
void
OverrideShouldNotify (bool override_value)
{
m_override_should_notify = override_value ? eLazyBoolYes : eLazyBoolNo;
}
// If should stop returns false, check if we should notify of this event
virtual bool
ShouldNotify (Event *event_ptr)
{
return false;
if (m_override_should_notify == eLazyBoolCalculate)
return DoShouldNotify (event_ptr);
else
return m_override_should_notify == eLazyBoolYes;
}
virtual void
@ -116,20 +125,19 @@ public:
void
OverrideShouldStop (bool override_value)
{
m_override_set = true;
m_override_value = override_value;
m_override_should_stop = override_value ? eLazyBoolYes : eLazyBoolNo;
}
bool
GetOverrideShouldStop()
{
return m_override_set;
return m_override_should_stop != eLazyBoolCalculate;
}
bool
GetOverriddenShouldStopValue ()
{
return m_override_value;
return m_override_should_stop == eLazyBoolYes;
}
static lldb::StopInfoSP
@ -169,6 +177,12 @@ protected:
{
}
virtual bool
DoShouldNotify (Event *event_ptr)
{
return false;
}
// Stop the thread by default. Subclasses can override this to allow
// the thread to continue if desired. The ShouldStop method should not do anything
// that might run code. If you need to run code when deciding whether to stop
@ -189,8 +203,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;
LazyBool m_override_should_notify;
LazyBool m_override_should_stop;
// This determines whether the target has run since this stop info.
// N.B. running to evaluate a user expression does not count.

View File

@ -288,7 +288,7 @@ public:
Vote
ShouldReportStop (Event *event_ptr);
Vote
ShouldReportRun (Event *event_ptr);
@ -927,6 +927,9 @@ public:
void
SetStopInfo (const lldb::StopInfoSP &stop_info_sp);
void
SetShouldReportStop (Vote vote);
protected:
friend class ThreadPlan;
@ -1015,7 +1018,7 @@ protected:
bool m_destroy_called; // This is used internally to make sure derived Thread classes call DestroyThread.
uint32_t m_thread_stop_reason_stop_id; // This is the stop id for which the StopInfo is valid. Can use this so you know that
// the thread's m_actual_stop_info_sp is current and you don't have to fetch it again
LazyBool m_override_should_notify;
private:
//------------------------------------------------------------------
// For Thread only

View File

@ -136,6 +136,9 @@ public:
protected:
void
SetShouldReportStop (Vote vote);
void
NotifySelectedThreadChanged (lldb::tid_t tid);

View File

@ -92,7 +92,8 @@ namespace lldb_private {
// When the target process is about to be restarted, the plan's WillResume method is called,
// giving the plan a chance to prepare for the run. If WillResume returns false, then the
// process is not restarted. Be sure to set an appropriate error value in the Process if
// you have to do this.
// you have to do this. Note, ThreadPlans actually implement DoWillResume, WillResume wraps that call.
//
// Next the "StopOthers" method of all the threads are polled, and if one thread's Current plan
// returns "true" then only that thread gets to run. If more than one returns "true" the threads that want to run solo
// get run one by one round robin fashion. Otherwise all are let to run.
@ -115,6 +116,8 @@ namespace lldb_private {
// figure out what to do about the plans below it in the stack. If the stop is recoverable, then the plan that
// understands it can just do what it needs to set up to restart, and then continue.
// Otherwise, the plan that understood the stop should call DiscardPlanStack to clean up the stack below it.
// Note, plans actually implement DoPlanExplainsStop, the result is cached in PlanExplainsStop so the DoPlanExplainsStop
// itself will only get called once per stop.
//
// Master plans:
//
@ -331,9 +334,6 @@ public:
virtual bool
ValidatePlan (Stream *error) = 0;
virtual bool
PlanExplainsStop (Event *event_ptr) = 0;
bool
TracerExplainsStop ()
{
@ -347,6 +347,9 @@ public:
lldb::StateType
RunState ();
bool
PlanExplainsStop (Event *event_ptr);
virtual bool
ShouldStop (Event *event_ptr) = 0;
@ -371,9 +374,11 @@ public:
virtual bool
StopOthers ();
virtual bool
// This is the wrapper for DoWillResume that does generic ThreadPlan logic, then
// calls DoWillResume.
bool
WillResume (lldb::StateType resume_state, bool current_plan);
virtual bool
WillStop () = 0;
@ -510,6 +515,12 @@ protected:
// Classes that inherit from ThreadPlan can see and modify these
//------------------------------------------------------------------
virtual bool
DoWillResume (lldb::StateType resume_state, bool current_plan) { return true; };
virtual bool
DoPlanExplainsStop (Event *event_ptr) = 0;
// This gets the previous plan to the current plan (for forwarding requests).
// This is mostly a formal requirement, it allows us to make the Thread's
// GetPreviousPlan protected, but only friend ThreadPlan to thread.
@ -535,6 +546,18 @@ protected:
m_thread.SetStopInfo (stop_reason_sp);
}
void
CachePlanExplainsStop (bool does_explain)
{
m_cached_plan_explains_stop = does_explain ? eLazyBoolYes : eLazyBoolNo;
}
LazyBool
GetCachedPlanExplainsStop () const
{
return m_cached_plan_explains_stop;
}
virtual lldb::StateType
GetPlanRunState () = 0;
@ -551,6 +574,7 @@ private:
ThreadPlanKind m_kind;
std::string m_name;
Mutex m_plan_complete_mutex;
LazyBool m_cached_plan_explains_stop;
bool m_plan_complete;
bool m_plan_private;
bool m_okay_to_discard;

View File

@ -35,13 +35,12 @@ public:
virtual void GetDescription (Stream *s, lldb::DescriptionLevel level);
virtual bool ValidatePlan (Stream *error);
virtual bool PlanExplainsStop (Event *event_ptr);
virtual bool ShouldStop (Event *event_ptr);
virtual Vote ShouldReportStop (Event *event_ptr);
virtual bool StopOthers ();
virtual lldb::StateType GetPlanRunState ();
virtual bool WillStop ();
virtual bool MischiefManaged ();
virtual bool WillResume (lldb::StateType resume_state, bool current_plan);
virtual bool OkayToDiscard()
{
@ -55,6 +54,8 @@ public:
}
protected:
virtual bool DoWillResume (lldb::StateType resume_state, bool current_plan);
virtual bool DoPlanExplainsStop (Event *event_ptr);
ThreadPlanBase (Thread &thread);
private:

View File

@ -58,9 +58,6 @@ public:
virtual bool
ValidatePlan (Stream *error);
virtual bool
PlanExplainsStop (Event *event_ptr);
virtual bool
ShouldStop (Event *event_ptr);
@ -135,8 +132,12 @@ public:
virtual bool
RestoreThreadState();
protected:
protected:
void ReportRegisterState (const char *message);
virtual bool
DoPlanExplainsStop (Event *event_ptr);
private:
bool

View File

@ -46,9 +46,6 @@ public:
virtual bool
ValidatePlan (Stream *error);
virtual bool
PlanExplainsStop (Event *event_ptr);
virtual bool
ShouldStop (Event *event_ptr);
@ -68,6 +65,9 @@ public:
MischiefManaged ();
protected:
virtual bool
DoPlanExplainsStop (Event *event_ptr);
void SetInitialBreakpoints();
bool AtOurAddress();
private:

View File

@ -59,13 +59,12 @@ public:
static void
SetDefaultFlagValue (uint32_t new_value);
virtual bool
PlanExplainsStop (Event *event_ptr);
virtual bool WillResume (lldb::StateType resume_state, bool current_plan);
protected:
virtual bool DoWillResume (lldb::StateType resume_state, bool current_plan);
virtual bool
DoPlanExplainsStop (Event *event_ptr);
virtual void
SetFlagsToDefault ();

View File

@ -27,7 +27,6 @@ public:
virtual void GetDescription (Stream *s, lldb::DescriptionLevel level);
virtual bool ValidatePlan (Stream *error);
virtual bool PlanExplainsStop (Event *event_ptr);
virtual bool ShouldStop (Event *event_ptr);
virtual bool StopOthers ();
virtual lldb::StateType GetPlanRunState ();
@ -35,6 +34,8 @@ public:
virtual bool MischiefManaged ();
protected:
virtual bool DoPlanExplainsStop (Event *event_ptr);
ThreadPlanStepInstruction (Thread &thread,
bool step_over,
bool stop_others,

View File

@ -34,11 +34,9 @@ public:
virtual void GetDescription (Stream *s, lldb::DescriptionLevel level);
virtual bool ValidatePlan (Stream *error);
virtual bool PlanExplainsStop (Event *event_ptr);
virtual bool ShouldStop (Event *event_ptr);
virtual bool StopOthers ();
virtual lldb::StateType GetPlanRunState ();
virtual bool WillResume (lldb::StateType resume_state, bool current_plan);
virtual bool WillStop ();
virtual bool MischiefManaged ();
virtual void DidPush();
@ -50,6 +48,8 @@ public:
}
protected:
virtual bool DoPlanExplainsStop (Event *event_ptr);
virtual bool DoWillResume (lldb::StateType resume_state, bool current_plan);
bool QueueInlinedStepPlan (bool queue_now);
private:

View File

@ -27,17 +27,17 @@ public:
ThreadPlanStepOverBreakpoint (Thread &thread);
virtual void GetDescription (Stream *s, lldb::DescriptionLevel level);
virtual bool ValidatePlan (Stream *error);
virtual bool PlanExplainsStop (Event *event_ptr);
virtual bool ShouldStop (Event *event_ptr);
virtual bool StopOthers ();
virtual lldb::StateType GetPlanRunState ();
virtual bool WillResume (lldb::StateType resume_state, bool current_plan);
virtual bool WillStop ();
virtual bool MischiefManaged ();
void SetAutoContinue (bool do_it);
virtual bool ShouldAutoContinue(Event *event_ptr);
protected:
virtual bool DoPlanExplainsStop (Event *event_ptr);
virtual bool DoWillResume (lldb::StateType resume_state, bool current_plan);
private:

View File

@ -34,10 +34,10 @@ public:
virtual void GetDescription (Stream *s, lldb::DescriptionLevel level);
virtual bool ShouldStop (Event *event_ptr);
virtual bool PlanExplainsStop (Event *event_ptr);
virtual bool WillResume (lldb::StateType resume_state, bool current_plan);
protected:
virtual bool DoPlanExplainsStop (Event *event_ptr);
virtual bool DoWillResume (lldb::StateType resume_state, bool current_plan);
private:

View File

@ -26,16 +26,17 @@ public:
virtual void GetDescription (Stream *s, lldb::DescriptionLevel level);
virtual bool ValidatePlan (Stream *error);
virtual bool PlanExplainsStop (Event *event_ptr);
virtual bool ShouldStop (Event *event_ptr);
virtual bool StopOthers ();
virtual lldb::StateType GetPlanRunState ();
virtual bool WillResume (lldb::StateType resume_state, bool current_plan);
virtual bool WillStop ();
virtual bool MischiefManaged ();
virtual void DidPush();
protected:
virtual bool DoPlanExplainsStop (Event *event_ptr);
virtual bool DoWillResume (lldb::StateType resume_state, bool current_plan);
ThreadPlanStepThrough (Thread &thread,
StackID &return_stack_id,
bool stop_others);

View File

@ -27,15 +27,16 @@ public:
virtual void GetDescription (Stream *s, lldb::DescriptionLevel level);
virtual bool ValidatePlan (Stream *error);
virtual bool PlanExplainsStop (Event *event_ptr);
virtual bool ShouldStop (Event *event_ptr);
virtual bool StopOthers ();
virtual lldb::StateType GetPlanRunState ();
virtual bool WillResume (lldb::StateType resume_state, bool current_plan);
virtual bool WillStop ();
virtual bool MischiefManaged ();
protected:
virtual bool DoWillResume (lldb::StateType resume_state, bool current_plan);
virtual bool DoPlanExplainsStop (Event *event_ptr);
ThreadPlanStepUntil (Thread &thread,
lldb::addr_t *address_list,
size_t num_addresses,

View File

@ -79,7 +79,11 @@
isEnabled = "YES">
</CommandLineArgument>
<CommandLineArgument
argument = "python_api/hello_world"
argument = "-f"
isEnabled = "YES">
</CommandLineArgument>
<CommandLineArgument
argument = "ConditionalBreakTestCase.test_with_dwarf_command"
isEnabled = "YES">
</CommandLineArgument>
</CommandLineArguments>

View File

@ -126,7 +126,7 @@ AppleThreadPlanStepThroughObjCTrampoline::ValidatePlan (Stream *error)
}
bool
AppleThreadPlanStepThroughObjCTrampoline::PlanExplainsStop (Event *event_ptr)
AppleThreadPlanStepThroughObjCTrampoline::DoPlanExplainsStop (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

View File

@ -45,10 +45,6 @@ public:
virtual bool
ValidatePlan (Stream *error);
virtual bool
PlanExplainsStop (Event *event_ptr);
virtual lldb::StateType
GetPlanRunState ();
@ -81,6 +77,8 @@ protected:
//------------------------------------------------------------------
// Classes that inherit from AppleThreadPlanStepThroughObjCTrampoline can see and modify these
//------------------------------------------------------------------
virtual bool
DoPlanExplainsStop (Event *event_ptr);
private:
bool

View File

@ -1643,11 +1643,11 @@ Process::GetState()
}
void
Process::SetPublicState (StateType new_state)
Process::SetPublicState (StateType new_state, bool restarted)
{
Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_STATE | LIBLLDB_LOG_PROCESS));
if (log)
log->Printf("Process::SetPublicState (%s)", StateAsCString(new_state));
log->Printf("Process::SetPublicState (state = %s, restarted = %i)", StateAsCString(new_state), restarted);
const StateType old_state = m_public_state.GetValue();
m_public_state.SetValue (new_state);
@ -1666,9 +1666,9 @@ Process::SetPublicState (StateType new_state)
{
const bool old_state_is_stopped = StateIsStoppedState(old_state, false);
const bool new_state_is_stopped = StateIsStoppedState(new_state, false);
if (old_state_is_stopped != new_state_is_stopped)
if ((old_state_is_stopped != new_state_is_stopped))
{
if (new_state_is_stopped)
if (new_state_is_stopped && !restarted)
{
if (log)
log->Printf("Process::SetPublicState (%s) -- unlocking run lock", StateAsCString(new_state));
@ -2866,7 +2866,8 @@ Process::Launch (const ProcessLaunchInfo &launch_info)
error = WillLaunch (exe_module);
if (error.Success())
{
SetPublicState (eStateLaunching);
const bool restarted = false;
SetPublicState (eStateLaunching, restarted);
m_should_detach = false;
if (m_public_run_lock.WriteTryLock())
@ -2993,11 +2994,13 @@ Process::AttachCompletionHandler::PerformAction (lldb::EventSP &event_sp)
// During attach, prior to sending the eStateStopped event,
// lldb_private::Process subclasses must set the new process ID.
assert (m_process->GetID() != LLDB_INVALID_PROCESS_ID);
// We don't want these events to be reported, so go set the ShouldReportStop here:
m_process->GetThreadList().SetShouldReportStop (eVoteNo);
if (m_exec_count > 0)
{
--m_exec_count;
m_process->PrivateResume ();
Process::ProcessEventData::SetRestartedInEvent (event_sp.get(), true);
RequestResume();
return eEventActionRetry;
}
else
@ -3056,7 +3059,8 @@ Process::Attach (ProcessAttachInfo &attach_info)
if (m_public_run_lock.WriteTryLock())
{
m_should_detach = true;
SetPublicState (eStateAttaching);
const bool restarted = false;
SetPublicState (eStateAttaching, restarted);
// Now attach using these arguments.
error = DoAttachToProcessWithName (process_name, wait_for_launch, attach_info);
}
@ -3134,7 +3138,8 @@ Process::Attach (ProcessAttachInfo &attach_info)
{
// Now attach using these arguments.
m_should_detach = true;
SetPublicState (eStateAttaching);
const bool restarted = false;
SetPublicState (eStateAttaching, restarted);
error = DoAttachToProcessWithID (attach_pid, attach_info);
}
else
@ -3287,7 +3292,7 @@ Process::PrivateResume ()
// that they are supposed to have when the process is resumed
// (suspended/running/stepping). Threads should also check
// their resume signal in lldb::Thread::GetResumeSignal()
// to see if they are suppoed to start back up with a signal.
// to see if they are supposed to start back up with a signal.
if (m_thread_list.WillResume())
{
// Last thing, do the PreResumeActions.
@ -3677,6 +3682,7 @@ Process::ShouldBroadcastEvent (Event *event_ptr)
// If we are going to stop, then we always broadcast the event.
// If we aren't going to stop, let the thread plans decide if we're going to report this event.
// If no thread has an opinion, we don't report it.
RefreshStateAfterStop ();
if (ProcessEventData::GetInterruptedFromEvent (event_ptr))
{
@ -3688,15 +3694,17 @@ Process::ShouldBroadcastEvent (Event *event_ptr)
}
else
{
bool was_restarted = ProcessEventData::GetRestartedFromEvent (event_ptr);
bool should_resume = 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)
if (was_restarted || should_resume || m_resume_requested)
{
Vote stop_vote = m_thread_list.ShouldReportStop (event_ptr);
if (log)
@ -3883,6 +3891,8 @@ void
Process::HandlePrivateEvent (EventSP &event_sp)
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
m_resume_requested = false;
m_currently_handling_event.SetValue(true, eBroadcastNever);
const StateType new_state = Process::ProcessEventData::GetStateFromEvent(event_sp.get());
@ -3911,6 +3921,7 @@ Process::HandlePrivateEvent (EventSP &event_sp)
{
// FIXME: should cons up an exited event, and discard this one.
SetExitStatus(0, m_next_event_action_ap->GetExitString());
m_currently_handling_event.SetValue(false, eBroadcastAlways);
SetNextEventAction(NULL);
return;
}
@ -4095,12 +4106,11 @@ Process::ProcessEventData::DoOnRemoval (Event *event_ptr)
// the public event queue, then other times when we're pretending that this is where we stopped at the
// end of expression evaluation. m_update_state is used to distinguish these
// three cases; it is 0 when we're just pulling it off for private handling,
// and > 1 for expression evaluation, and we don't want to do the breakpoint command handling then.
// and > 1 for expression evaluation, and we don't want to do the breakpoint command handling then.
if (m_update_state != 1)
return;
m_process_sp->SetPublicState (m_state);
m_process_sp->SetPublicState (m_state, Process::ProcessEventData::GetRestartedFromEvent(event_ptr));
// If we're stopped and haven't restarted, then do the breakpoint commands here:
if (m_state == eStateStopped && ! m_restarted)

View File

@ -39,8 +39,8 @@ StopInfo::StopInfo (Thread &thread, uint64_t value) :
m_stop_id (thread.GetProcess()->GetStopID()),
m_resume_id (thread.GetProcess()->GetResumeID()),
m_value (value),
m_override_set(false),
m_override_value(true)
m_override_should_notify (eLazyBoolCalculate),
m_override_should_stop (eLazyBoolCalculate)
{
}
@ -201,7 +201,7 @@ public:
}
virtual bool
ShouldNotify (Event *event_ptr)
DoShouldNotify (Event *event_ptr)
{
ThreadSP thread_sp (m_thread_wp.lock());
if (thread_sp)
@ -849,7 +849,7 @@ public:
// If should stop returns false, check if we should notify of this event
virtual bool
ShouldNotify (Event *event_ptr)
DoShouldNotify (Event *event_ptr)
{
ThreadSP thread_sp (m_thread_wp.lock());
if (thread_sp)

View File

@ -259,7 +259,8 @@ Thread::Thread (Process &process, lldb::tid_t tid) :
m_temporary_resume_state (eStateRunning),
m_unwinder_ap (),
m_destroy_called (false),
m_thread_stop_reason_stop_id (0)
m_thread_stop_reason_stop_id (0),
m_override_should_notify (eLazyBoolCalculate)
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
if (log)
@ -394,7 +395,13 @@ Thread::SetStopInfo (const lldb::StopInfoSP &stop_info_sp)
{
m_actual_stop_info_sp = stop_info_sp;
if (m_actual_stop_info_sp)
{
m_actual_stop_info_sp->MakeStopInfoValid();
// If we are overriding the ShouldReportStop, do that here:
if (m_override_should_notify != eLazyBoolCalculate)
m_actual_stop_info_sp->OverrideShouldNotify (m_override_should_notify == eLazyBoolYes);
}
ProcessSP process_sp (GetProcess());
if (process_sp)
m_thread_stop_reason_stop_id = process_sp->GetStopID();
@ -402,6 +409,19 @@ Thread::SetStopInfo (const lldb::StopInfoSP &stop_info_sp)
m_thread_stop_reason_stop_id = UINT32_MAX;
}
void
Thread::SetShouldReportStop (Vote vote)
{
if (vote == eVoteNoOpinion)
return;
else
{
m_override_should_notify = (vote == eVoteYes ? eLazyBoolYes : eLazyBoolNo);
if (m_actual_stop_info_sp)
m_actual_stop_info_sp->OverrideShouldNotify (m_override_should_notify == eLazyBoolYes);
}
}
void
Thread::SetStopInfoToNothing()
{
@ -530,6 +550,7 @@ Thread::ShouldResume (StateType resume_state)
// At this point clear the completed plan stack.
m_completed_plan_stack.clear();
m_discarded_plan_stack.clear();
m_override_should_notify = eLazyBoolCalculate;
m_temporary_resume_state = resume_state;

View File

@ -376,6 +376,19 @@ ThreadList::ShouldReportStop (Event *event_ptr)
return result;
}
void
ThreadList::SetShouldReportStop (Vote vote)
{
Mutex::Locker locker(GetMutex());
m_process->UpdateThreadListIfNeeded();
collection::iterator pos, end = m_threads.end();
for (pos = m_threads.begin(); pos != end; ++pos)
{
ThreadSP thread_sp(*pos);
thread_sp->SetShouldReportStop (vote);
}
}
Vote
ThreadList::ShouldReportRun (Event *event_ptr)
{

View File

@ -36,6 +36,7 @@ ThreadPlan::ThreadPlan(ThreadPlanKind kind, const char *name, Thread &thread, Vo
m_kind (kind),
m_name (name),
m_plan_complete_mutex (Mutex::eMutexTypeRecursive),
m_cached_plan_explains_stop (eLazyBoolCalculate),
m_plan_complete (false),
m_plan_private (false),
m_okay_to_discard (true),
@ -52,6 +53,21 @@ ThreadPlan::~ThreadPlan()
{
}
bool
ThreadPlan::PlanExplainsStop (Event *event_ptr)
{
if (m_cached_plan_explains_stop == eLazyBoolCalculate)
{
bool actual_value = DoPlanExplainsStop(event_ptr);
m_cached_plan_explains_stop = actual_value ? eLazyBoolYes : eLazyBoolNo;
return actual_value;
}
else
{
return m_cached_plan_explains_stop == eLazyBoolYes;
}
}
bool
ThreadPlan::IsPlanComplete ()
{
@ -131,6 +147,8 @@ ThreadPlan::SetStopOthers (bool new_value)
bool
ThreadPlan::WillResume (StateType resume_state, bool current_plan)
{
m_cached_plan_explains_stop = eLazyBoolCalculate;
if (current_plan)
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
@ -154,7 +172,7 @@ ThreadPlan::WillResume (StateType resume_state, bool current_plan)
StopOthers());
}
}
return true;
return DoWillResume (resume_state, current_plan);
}
lldb::user_id_t

View File

@ -68,7 +68,7 @@ ThreadPlanBase::ValidatePlan (Stream *error)
}
bool
ThreadPlanBase::PlanExplainsStop (Event *event_ptr)
ThreadPlanBase::DoPlanExplainsStop (Event *event_ptr)
{
// The base plan should defer to its tracer, since by default it
// always handles the stop.
@ -78,6 +78,22 @@ ThreadPlanBase::PlanExplainsStop (Event *event_ptr)
return true;
}
Vote
ThreadPlanBase::ShouldReportStop(Event *event_ptr)
{
StopInfoSP stop_info_sp = m_thread.GetStopInfo ();
if (stop_info_sp)
{
bool should_notify = stop_info_sp->ShouldNotify(event_ptr);
if (should_notify)
return eVoteYes;
else
return eVoteNoOpinion;
}
else
return eVoteNoOpinion;
}
bool
ThreadPlanBase::ShouldStop (Event *event_ptr)
{
@ -201,7 +217,7 @@ ThreadPlanBase::WillStop ()
}
bool
ThreadPlanBase::WillResume (lldb::StateType resume_state, bool current_plan)
ThreadPlanBase::DoWillResume (lldb::StateType resume_state, bool current_plan)
{
// Reset these to the default values so we don't set them wrong, then not get asked
// for a while, then return the wrong answer.

View File

@ -362,7 +362,7 @@ ThreadPlanCallFunction::ShouldReportStop(Event *event_ptr)
}
bool
ThreadPlanCallFunction::PlanExplainsStop (Event *event_ptr)
ThreadPlanCallFunction::DoPlanExplainsStop (Event *event_ptr)
{
Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_STEP|LIBLLDB_LOG_PROCESS));
m_real_stop_info_sp = GetPrivateStopReason();
@ -475,9 +475,9 @@ ThreadPlanCallFunction::PlanExplainsStop (Event *event_ptr)
bool
ThreadPlanCallFunction::ShouldStop (Event *event_ptr)
{
// We do some computation in PlanExplainsStop that may or may not set the plan as complete.
// We do some computation in DoPlanExplainsStop that may or may not set the plan as complete.
// We need to do that here to make sure our state is correct.
PlanExplainsStop(event_ptr);
DoPlanExplainsStop(event_ptr);
if (IsPlanComplete())
{

View File

@ -188,7 +188,7 @@ ThreadPlanRunToAddress::ValidatePlan (Stream *error)
}
bool
ThreadPlanRunToAddress::PlanExplainsStop (Event *event_ptr)
ThreadPlanRunToAddress::DoPlanExplainsStop (Event *event_ptr)
{
return AtOurAddress();
}

View File

@ -379,7 +379,7 @@ ThreadPlanStepInRange::DefaultShouldStopHereCallback (ThreadPlan *current_plan,
}
bool
ThreadPlanStepInRange::PlanExplainsStop (Event *event_ptr)
ThreadPlanStepInRange::DoPlanExplainsStop (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
@ -394,41 +394,54 @@ ThreadPlanStepInRange::PlanExplainsStop (Event *event_ptr)
//
// The only variation is that if we are doing "step by running to next branch" in which case
// if we hit our branch breakpoint we don't set the plan to complete.
bool return_value;
if (m_virtual_step)
return true;
StopInfoSP stop_info_sp = GetPrivateStopReason();
if (stop_info_sp)
{
StopReason reason = stop_info_sp->GetStopReason();
switch (reason)
{
case eStopReasonBreakpoint:
if (NextRangeBreakpointExplainsStop(stop_info_sp))
return true;
case eStopReasonWatchpoint:
case eStopReasonSignal:
case eStopReasonException:
case eStopReasonExec:
case eStopReasonThreadExiting:
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
if (log)
log->PutCString ("ThreadPlanStepInRange got asked if it explains the stop for some reason other than step.");
}
return false;
break;
default:
break;
}
return_value = true;
}
return true;
else
{
StopInfoSP stop_info_sp = GetPrivateStopReason();
if (stop_info_sp)
{
StopReason reason = stop_info_sp->GetStopReason();
switch (reason)
{
case eStopReasonBreakpoint:
if (NextRangeBreakpointExplainsStop(stop_info_sp))
{
return_value = true;
break;
}
case eStopReasonWatchpoint:
case eStopReasonSignal:
case eStopReasonException:
case eStopReasonExec:
case eStopReasonThreadExiting:
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
if (log)
log->PutCString ("ThreadPlanStepInRange got asked if it explains the stop for some reason other than step.");
}
return_value = false;
break;
default:
return_value = true;
break;
}
}
else
return_value = true;
}
return return_value;
}
bool
ThreadPlanStepInRange::WillResume (lldb::StateType resume_state, bool current_plan)
ThreadPlanStepInRange::DoWillResume (lldb::StateType resume_state, bool current_plan)
{
if (resume_state == eStateStepping && current_plan)
{
@ -438,7 +451,7 @@ ThreadPlanStepInRange::WillResume (lldb::StateType resume_state, bool current_pl
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
if (log)
log->Printf ("ThreadPlanStepInRange::WillResume: returning false, inline_depth: %d",
log->Printf ("ThreadPlanStepInRange::DoWillResume: returning false, inline_depth: %d",
m_thread.GetCurrentInlinedDepth());
SetStopInfo(StopInfo::CreateStopReasonToTrace(m_thread));
@ -448,7 +461,5 @@ ThreadPlanStepInRange::WillResume (lldb::StateType resume_state, bool current_pl
}
return !step_without_resume;
}
else
return ThreadPlan::WillResume(resume_state, current_plan);
return true;
}

View File

@ -81,7 +81,7 @@ ThreadPlanStepInstruction::ValidatePlan (Stream *error)
}
bool
ThreadPlanStepInstruction::PlanExplainsStop (Event *event_ptr)
ThreadPlanStepInstruction::DoPlanExplainsStop (Event *event_ptr)
{
StopInfoSP stop_info_sp = GetPrivateStopReason();
if (stop_info_sp)

View File

@ -174,7 +174,7 @@ ThreadPlanStepOut::ValidatePlan (Stream *error)
}
bool
ThreadPlanStepOut::PlanExplainsStop (Event *event_ptr)
ThreadPlanStepOut::DoPlanExplainsStop (Event *event_ptr)
{
// If one of our child plans just finished, then we do explain the stop.
if (m_step_out_plan_sp)
@ -336,9 +336,8 @@ ThreadPlanStepOut::GetPlanRunState ()
}
bool
ThreadPlanStepOut::WillResume (StateType resume_state, bool current_plan)
ThreadPlanStepOut::DoWillResume (StateType resume_state, bool current_plan)
{
ThreadPlan::WillResume (resume_state, current_plan);
if (m_step_out_plan_sp || m_step_through_inline_plan_sp)
return true;

View File

@ -58,7 +58,7 @@ ThreadPlanStepOverBreakpoint::ValidatePlan (Stream *error)
}
bool
ThreadPlanStepOverBreakpoint::PlanExplainsStop (Event *event_ptr)
ThreadPlanStepOverBreakpoint::DoPlanExplainsStop (Event *event_ptr)
{
StopInfoSP stop_info_sp = GetPrivateStopReason();
if (stop_info_sp)
@ -91,10 +91,8 @@ ThreadPlanStepOverBreakpoint::GetPlanRunState ()
}
bool
ThreadPlanStepOverBreakpoint::WillResume (StateType resume_state, bool current_plan)
ThreadPlanStepOverBreakpoint::DoWillResume (StateType resume_state, bool current_plan)
{
ThreadPlan::WillResume (resume_state, current_plan);
if (current_plan)
{
BreakpointSiteSP bp_site_sp (m_thread.GetProcess()->GetBreakpointSiteList().FindByAddress (m_breakpoint_addr));

View File

@ -290,7 +290,7 @@ ThreadPlanStepOverRange::ShouldStop (Event *event_ptr)
}
bool
ThreadPlanStepOverRange::PlanExplainsStop (Event *event_ptr)
ThreadPlanStepOverRange::DoPlanExplainsStop (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
@ -301,6 +301,8 @@ ThreadPlanStepOverRange::PlanExplainsStop (Event *event_ptr)
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
StopInfoSP stop_info_sp = GetPrivateStopReason();
bool return_value;
if (stop_info_sp)
{
StopReason reason = stop_info_sp->GetStopReason();
@ -308,13 +310,13 @@ ThreadPlanStepOverRange::PlanExplainsStop (Event *event_ptr)
switch (reason)
{
case eStopReasonTrace:
return true;
return_value = true;
break;
case eStopReasonBreakpoint:
if (NextRangeBreakpointExplainsStop(stop_info_sp))
return true;
return_value = true;
else
return false;
return_value = false;
break;
case eStopReasonWatchpoint:
case eStopReasonSignal:
@ -324,15 +326,18 @@ ThreadPlanStepOverRange::PlanExplainsStop (Event *event_ptr)
default:
if (log)
log->PutCString ("ThreadPlanStepInRange got asked if it explains the stop for some reason other than step.");
return false;
return_value = false;
break;
}
}
return true;
else
return_value = true;
return return_value;
}
bool
ThreadPlanStepOverRange::WillResume (lldb::StateType resume_state, bool current_plan)
ThreadPlanStepOverRange::DoWillResume (lldb::StateType resume_state, bool current_plan)
{
if (resume_state != eStateSuspended && m_first_resume)
{
@ -346,7 +351,7 @@ ThreadPlanStepOverRange::WillResume (lldb::StateType resume_state, bool current_
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
if (log)
log->Printf ("ThreadPlanStepInRange::WillResume: adjusting range to the frame at inlined depth %d.",
log->Printf ("ThreadPlanStepInRange::DoWillResume: adjusting range to the frame at inlined depth %d.",
m_thread.GetCurrentInlinedDepth());
StackFrameSP stack_sp = m_thread.GetStackFrameAtIndex(0);
if (stack_sp)
@ -379,5 +384,5 @@ ThreadPlanStepOverRange::WillResume (lldb::StateType resume_state, bool current_
}
}
return ThreadPlan::WillResume(resume_state, current_plan);
return true;
}

View File

@ -139,7 +139,7 @@ ThreadPlanStepThrough::ValidatePlan (Stream *error)
}
bool
ThreadPlanStepThrough::PlanExplainsStop (Event *event_ptr)
ThreadPlanStepThrough::DoPlanExplainsStop (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
@ -223,9 +223,8 @@ ThreadPlanStepThrough::GetPlanRunState ()
}
bool
ThreadPlanStepThrough::WillResume (StateType resume_state, bool current_plan)
ThreadPlanStepThrough::DoWillResume (StateType resume_state, bool current_plan)
{
ThreadPlan::WillResume(resume_state, current_plan);
return true;
}

View File

@ -305,7 +305,7 @@ ThreadPlanStepUntil::AnalyzeStop()
}
bool
ThreadPlanStepUntil::PlanExplainsStop (Event *event_ptr)
ThreadPlanStepUntil::DoPlanExplainsStop (Event *event_ptr)
{
// We don't explain signals or breakpoints (breakpoints that handle stepping in or
// out will be handled by a child plan.
@ -341,9 +341,8 @@ ThreadPlanStepUntil::GetPlanRunState ()
}
bool
ThreadPlanStepUntil::WillResume (StateType resume_state, bool current_plan)
ThreadPlanStepUntil::DoWillResume (StateType resume_state, bool current_plan)
{
ThreadPlan::WillResume (resume_state, current_plan);
if (current_plan)
{
TargetSP target_sp (m_thread.CalculateTarget());

View File

@ -129,6 +129,8 @@ class ObjCDynamicValueTestCase(TestBase):
threads = lldbutil.get_stopped_threads (process, lldb.eStopReasonPlanComplete)
self.assertTrue (len(threads) == 1)
line_entry = threads[0].GetFrameAtIndex(0).GetLineEntry()
print "Line entry is: ", line_entry
self.assertTrue (line_entry.GetLine() == self.set_property_line)
self.assertTrue (line_entry.GetFileSpec().GetFilename() == self.source_name)