summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJim Ingham <jingham@apple.com>2014-04-08 21:33:21 +0000
committerJim Ingham <jingham@apple.com>2014-04-08 21:33:21 +0000
commit35878c47522ba6bff8830f0b37e87d544b25650b (patch)
tree8e5316af77b0510d34d6213b532204392831ee10
parentb2fdacf3f28168f3c2a7bdcea2d4218146851544 (diff)
downloadbcm5719-llvm-35878c47522ba6bff8830f0b37e87d544b25650b.tar.gz
bcm5719-llvm-35878c47522ba6bff8830f0b37e87d544b25650b.zip
Fix the behavior when hand-calling a function times out on one thread,
but by the time we go to halt, it has already stopped by hitting the function end breakpoint. That wasn't being shown to the threads so the Function call thread plan didn't know its job was done. <rdar://problem/16515785> llvm-svn: 205803
-rw-r--r--lldb/source/Target/Process.cpp37
-rw-r--r--lldb/source/Target/ThreadList.cpp11
-rw-r--r--lldb/source/Target/ThreadPlanCallFunction.cpp8
3 files changed, 51 insertions, 5 deletions
diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp
index db992dde4de..1259b72993c 100644
--- a/lldb/source/Target/Process.cpp
+++ b/lldb/source/Target/Process.cpp
@@ -3901,6 +3901,9 @@ Process::ShouldBroadcastEvent (Event *event_ptr)
log->Printf ("Process::ShouldBroadcastEvent (%p) stopped due to an interrupt, state: %s",
static_cast<void*>(event_ptr),
StateAsCString(state));
+ // Even though we know we are going to stop, we should let the threads have a look at the stop,
+ // so they can properly set their state.
+ m_thread_list.ShouldStop (event_ptr);
return_value = true;
}
else
@@ -4381,8 +4384,14 @@ Process::ProcessEventData::DoOnRemoval (Event *event_ptr)
return;
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 this is a halt event, even if the halt stopped with some reason other than a plain interrupt (e.g. we had
+ // already stopped for a breakpoint when the halt request came through) don't do the StopInfo actions, as they may
+ // end up restarting the process.
+ if (m_interrupted)
+ return;
+
+ // If we're stopped and haven't restarted, then do the StopInfo actions here:
if (m_state == eStateStopped && ! m_restarted)
{
ThreadList &curr_thread_list = m_process_sp->GetThreadList();
@@ -5253,7 +5262,17 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,
// 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.
-
+
+#ifdef LLDB_RUN_THREAD_HALT_WITH_EVENT
+ // It's pretty much impossible to write test cases for things like:
+ // One thread timeout expires, I go to halt, but the process already stopped
+ // on the function call stop breakpoint. Turning on this define will make us not
+ // fetch the first event till after the halt. So if you run a quick function, it will have
+ // completed, and the completion event will be waiting, when you interrupt for halt.
+ // The expression evaluation should still succeed.
+ bool miss_first_event = true;
+#endif
+
while (1)
{
// We usually want to resume the process if we get to the top of the loop.
@@ -5383,7 +5402,17 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,
log->Printf ("Process::RunThreadPlan(): about to wait forever.");
}
}
-
+
+#ifdef LLDB_RUN_THREAD_HALT_WITH_EVENT
+ // See comment above...
+ if (miss_first_event)
+ {
+ usleep(1000);
+ miss_first_event = false;
+ got_event = false;
+ }
+ else
+#endif
got_event = listener.WaitForEvent (timeout_ptr, event_sp);
if (got_event)
diff --git a/lldb/source/Target/ThreadList.cpp b/lldb/source/Target/ThreadList.cpp
index 4fffdac9a34..7fb16fdac5c 100644
--- a/lldb/source/Target/ThreadList.cpp
+++ b/lldb/source/Target/ThreadList.cpp
@@ -262,7 +262,7 @@ ThreadList::ShouldStop (Event *event_ptr)
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
// The ShouldStop method of the threads can do a whole lot of work,
- // running breakpoint commands & conditions, etc. So we don't want
+ // figuring out whether the thread plan conditions are met. So we don't want
// to keep the ThreadList locked the whole time we are doing this.
// FIXME: It is possible that running code could cause new threads
// to be created. If that happens we will miss asking them whether
@@ -287,7 +287,16 @@ ThreadList::ShouldStop (Event *event_ptr)
}
bool did_anybody_stop_for_a_reason = false;
+
+ // If the event is an Interrupt event, then we're going to stop no matter what. Otherwise, presume we won't stop.
bool should_stop = false;
+ if (Process::ProcessEventData::GetInterruptedFromEvent(event_ptr))
+ {
+ if (log)
+ log->Printf("ThreadList::%s handling interrupt event, should stop set to true", __FUNCTION__);
+
+ should_stop = true;
+ }
// Now we run through all the threads and get their stop info's. We want to make sure to do this first before
// we start running the ShouldStop, because one thread's ShouldStop could destroy information (like deleting a
diff --git a/lldb/source/Target/ThreadPlanCallFunction.cpp b/lldb/source/Target/ThreadPlanCallFunction.cpp
index 0f2a0d32045..5a3ebd7b128 100644
--- a/lldb/source/Target/ThreadPlanCallFunction.cpp
+++ b/lldb/source/Target/ThreadPlanCallFunction.cpp
@@ -333,6 +333,14 @@ ThreadPlanCallFunction::DoPlanExplainsStop (Event *event_ptr)
if (stop_reason == eStopReasonBreakpoint && BreakpointsExplainStop())
return true;
+ // One more quirk here. If this event was from Halt interrupting the target, then we should not consider
+ // ourselves complete. Return true to acknowledge the stop.
+ if (Process::ProcessEventData::GetInterruptedFromEvent(event_ptr))
+ {
+ if (log)
+ log->Printf ("ThreadPlanCallFunction::PlanExplainsStop: The event is an Interrupt, returning true.");
+ return true;
+ }
// 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.
OpenPOWER on IntegriCloud