summaryrefslogtreecommitdiffstats
path: root/lldb
diff options
context:
space:
mode:
authorJim Ingham <jingham@apple.com>2012-07-27 23:57:19 +0000
committerJim Ingham <jingham@apple.com>2012-07-27 23:57:19 +0000
commitcfc0935ed958e75d2d3d50730d57c8ce2178704f (patch)
tree78155e58ebdae61441b292e943729ee4d284ed93 /lldb
parentae5bbfc0d00c89d2d63f37dce89804c4160cf50c (diff)
downloadbcm5719-llvm-cfc0935ed958e75d2d3d50730d57c8ce2178704f.tar.gz
bcm5719-llvm-cfc0935ed958e75d2d3d50730d57c8ce2178704f.zip
Added an lldb_private & equivalent SB API to send an AsyncInterrupt to the event loop.
Convert from calling Halt in the lldb Driver.cpp's input reader's sigint handler to sending this AsyncInterrupt so it can be handled in the event loop. If you are attaching and get an async interrupt, abort the attach attempt. Also remember to destroy the process if get interrupted while attaching. Getting this to work also required handing the eBroadcastBitInterrupt in a few more places in Process WaitForEvent & friends. <rdar://problem/10792425> llvm-svn: 160903
Diffstat (limited to 'lldb')
-rw-r--r--lldb/include/lldb/API/SBProcess.h3
-rw-r--r--lldb/include/lldb/Target/Process.h3
-rw-r--r--lldb/scripts/Python/interface/SBProcess.i3
-rw-r--r--lldb/source/API/SBProcess.cpp10
-rw-r--r--lldb/source/Commands/CommandObjectProcess.cpp1
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp2
-rw-r--r--lldb/source/Target/Process.cpp291
-rw-r--r--lldb/source/Target/TargetList.cpp2
-rw-r--r--lldb/tools/driver/Driver.cpp7
-rw-r--r--lldb/tools/driver/IOChannel.cpp10
10 files changed, 207 insertions, 125 deletions
diff --git a/lldb/include/lldb/API/SBProcess.h b/lldb/include/lldb/API/SBProcess.h
index c0d77bec2ee..e1814eebfa5 100644
--- a/lldb/include/lldb/API/SBProcess.h
+++ b/lldb/include/lldb/API/SBProcess.h
@@ -156,6 +156,9 @@ public:
lldb::SBError
Signal (int signal);
+ void
+ SendAsyncInterrupt();
+
size_t
ReadMemory (addr_t addr, void *buf, size_t size, lldb::SBError &error);
diff --git a/lldb/include/lldb/Target/Process.h b/lldb/include/lldb/Target/Process.h
index 265303ebeab..8a1b4c51083 100644
--- a/lldb/include/lldb/Target/Process.h
+++ b/lldb/include/lldb/Target/Process.h
@@ -2388,6 +2388,9 @@ public:
uint32_t num_frames,
uint32_t num_frames_with_source);
+ void
+ SendAsyncInterrupt ();
+
protected:
void
diff --git a/lldb/scripts/Python/interface/SBProcess.i b/lldb/scripts/Python/interface/SBProcess.i
index 018e2c20c44..1adc238c469 100644
--- a/lldb/scripts/Python/interface/SBProcess.i
+++ b/lldb/scripts/Python/interface/SBProcess.i
@@ -206,6 +206,9 @@ public:
lldb::SBError
Signal (int signal);
+ void
+ SendAsyncInterrupt();
+
%feature("autodoc", "
Reads memory from the current process's address space and removes any
traps that may have been inserted into the memory. It returns the byte
diff --git a/lldb/source/API/SBProcess.cpp b/lldb/source/API/SBProcess.cpp
index 801daa4bfc5..129f887108d 100644
--- a/lldb/source/API/SBProcess.cpp
+++ b/lldb/source/API/SBProcess.cpp
@@ -718,6 +718,16 @@ SBProcess::Signal (int signo)
return sb_error;
}
+void
+SBProcess::SendAsyncInterrupt ()
+{
+ ProcessSP process_sp(GetSP());
+ if (process_sp)
+ {
+ process_sp->SendAsyncInterrupt ();
+ }
+}
+
SBThread
SBProcess::GetThreadByID (tid_t tid)
{
diff --git a/lldb/source/Commands/CommandObjectProcess.cpp b/lldb/source/Commands/CommandObjectProcess.cpp
index f45e926adc6..97ed205a1b0 100644
--- a/lldb/source/Commands/CommandObjectProcess.cpp
+++ b/lldb/source/Commands/CommandObjectProcess.cpp
@@ -566,6 +566,7 @@ protected:
else
{
result.AppendError ("attach failed: process did not stop (no such process or permission problem?)");
+ process->Destroy();
result.SetStatus (eReturnStatusFailed);
return false;
}
diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
index 15f513d272a..35994bcb2d7 100644
--- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
@@ -1868,7 +1868,7 @@ ProcessGDBRemote::DoDestroy ()
{
if (log)
log->Printf ("ProcessGDBRemote::DoDestroy - failed to send k packet");
- exit_string.assign ("killing while attaching.");
+ exit_string.assign ("killed or interrupted while attaching.");
}
}
else
diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp
index 062b061c391..993d9809250 100644
--- a/lldb/source/Target/Process.cpp
+++ b/lldb/source/Target/Process.cpp
@@ -835,7 +835,8 @@ Process::Process(Target &target, Listener &listener) :
eBroadcastBitSTDERR);
m_private_state_listener.StartListeningForEvents(&m_private_state_broadcaster,
- eBroadcastBitStateChanged);
+ eBroadcastBitStateChanged |
+ eBroadcastBitInterrupt);
m_private_state_listener.StartListeningForEvents(&m_private_state_control_broadcaster,
eBroadcastInternalStateControlStop |
@@ -1027,7 +1028,7 @@ Process::HijackProcessEvents (Listener *listener)
{
if (listener != NULL)
{
- return HijackBroadcaster(listener, eBroadcastBitStateChanged);
+ return HijackBroadcaster(listener, eBroadcastBitStateChanged | eBroadcastBitInterrupt);
}
else
return false;
@@ -1044,7 +1045,7 @@ Process::HijackPrivateProcessEvents (Listener *listener)
{
if (listener != NULL)
{
- return m_private_state_broadcaster.HijackBroadcaster(listener, eBroadcastBitStateChanged);
+ return m_private_state_broadcaster.HijackBroadcaster(listener, eBroadcastBitStateChanged | eBroadcastBitInterrupt);
}
else
return false;
@@ -1067,9 +1068,14 @@ Process::WaitForStateChangedEvents (const TimeValue *timeout, EventSP &event_sp)
StateType state = eStateInvalid;
if (m_listener.WaitForEventForBroadcasterWithType (timeout,
this,
- eBroadcastBitStateChanged,
+ eBroadcastBitStateChanged | eBroadcastBitInterrupt,
event_sp))
- state = Process::ProcessEventData::GetStateFromEvent(event_sp.get());
+ {
+ if (event_sp && event_sp->GetType() == eBroadcastBitStateChanged)
+ state = Process::ProcessEventData::GetStateFromEvent(event_sp.get());
+ else if (log)
+ log->Printf ("Process::%s got no event or was interrupted.", __FUNCTION__);
+ }
if (log)
log->Printf ("Process::%s (timeout = %p, event_sp) => %s",
@@ -1118,9 +1124,10 @@ Process::WaitForStateChangedEventsPrivate (const TimeValue *timeout, EventSP &ev
StateType state = eStateInvalid;
if (m_private_state_listener.WaitForEventForBroadcasterWithType (timeout,
&m_private_state_broadcaster,
- eBroadcastBitStateChanged,
+ eBroadcastBitStateChanged | eBroadcastBitInterrupt,
event_sp))
- state = Process::ProcessEventData::GetStateFromEvent(event_sp.get());
+ if (event_sp && event_sp->GetType() == eBroadcastBitStateChanged)
+ state = Process::ProcessEventData::GetStateFromEvent(event_sp.get());
// This is a bit of a hack, but when we wait here we could very well return
// to the command-line, and that could disable the log, which would render the
@@ -3292,6 +3299,15 @@ Process::ControlPrivateStateThread (uint32_t signal)
}
void
+Process::SendAsyncInterrupt ()
+{
+ if (PrivateStateThreadIsValid())
+ m_private_state_broadcaster.BroadcastEvent (Process::eBroadcastBitInterrupt, NULL);
+ else
+ BroadcastEvent (Process::eBroadcastBitInterrupt, NULL);
+}
+
+void
Process::HandlePrivateEvent (EventSP &event_sp)
{
LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
@@ -3410,7 +3426,22 @@ Process::RunPrivateStateThread ()
m_private_state_control_wait.SetValue (true, eBroadcastAlways);
continue;
}
-
+ else if (event_sp->GetType() == eBroadcastBitInterrupt)
+ {
+ if (m_public_state.GetValue() == eStateAttaching)
+ {
+ if (log)
+ log->Printf ("Process::%s (arg = %p, pid = %llu) woke up with an interrupt while attaching - forwarding interrupt.", __FUNCTION__, this, GetID());
+ BroadcastEvent (eBroadcastBitInterrupt, NULL);
+ }
+ else
+ {
+ if (log)
+ log->Printf ("Process::%s (arg = %p, pid = %llu) woke up with an interrupt - Halting.", __FUNCTION__, this, GetID());
+ Halt();
+ }
+ continue;
+ }
const StateType internal_state = Process::ProcessEventData::GetStateFromEvent(event_sp.get());
@@ -4215,72 +4246,85 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,
if (event_sp.get())
{
bool keep_going = false;
- stop_state = Process::ProcessEventData::GetStateFromEvent(event_sp.get());
- if (log)
- log->Printf("Process::RunThreadPlan(): in while loop, got event: %s.", StateAsCString(stop_state));
-
- switch (stop_state)
+ if (event_sp->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.");
+ }
+ else
{
- case lldb::eStateStopped:
+ stop_state = Process::ProcessEventData::GetStateFromEvent(event_sp.get());
+ if (log)
+ log->Printf("Process::RunThreadPlan(): in while loop, got event: %s.", StateAsCString(stop_state));
+
+ switch (stop_state)
{
- // Yay, we're done. Now make sure that our thread plan actually completed.
- ThreadSP thread_sp = GetThreadList().FindThreadByIndexID (thread_idx_id);
- if (!thread_sp)
+ case lldb::eStateStopped:
{
- // Ooh, our thread has vanished. Unlikely that this was successful execution...
- if (log)
- log->Printf ("Process::RunThreadPlan(): execution completed but our thread (index-id=%u) has vanished.", thread_idx_id);
- return_value = eExecutionInterrupted;
- }
- else
- {
- StopInfoSP stop_info_sp (thread_sp->GetStopInfo ());
- StopReason stop_reason = eStopReasonInvalid;
- if (stop_info_sp)
- stop_reason = stop_info_sp->GetStopReason();
- if (stop_reason == eStopReasonPlanComplete)
+ // Yay, we're done. Now make sure that our thread plan actually completed.
+ ThreadSP thread_sp = GetThreadList().FindThreadByIndexID (thread_idx_id);
+ if (!thread_sp)
{
+ // Ooh, our thread has vanished. Unlikely that this was successful execution...
if (log)
- log->PutCString ("Process::RunThreadPlan(): execution completed successfully.");
- // Now mark this plan as private so it doesn't get reported as the stop reason
- // after this point.
- if (thread_plan_sp)
- thread_plan_sp->SetPrivate (orig_plan_private);
- return_value = eExecutionCompleted;
+ log->Printf ("Process::RunThreadPlan(): execution completed but our thread (index-id=%u) has vanished.", thread_idx_id);
+ return_value = eExecutionInterrupted;
}
else
{
- if (log)
- log->PutCString ("Process::RunThreadPlan(): thread plan didn't successfully complete.");
-
- return_value = eExecutionInterrupted;
+ StopInfoSP stop_info_sp (thread_sp->GetStopInfo ());
+ StopReason stop_reason = eStopReasonInvalid;
+ if (stop_info_sp)
+ stop_reason = stop_info_sp->GetStopReason();
+ if (stop_reason == eStopReasonPlanComplete)
+ {
+ if (log)
+ log->PutCString ("Process::RunThreadPlan(): execution completed successfully.");
+ // Now mark this plan as private so it doesn't get reported as the stop reason
+ // after this point.
+ if (thread_plan_sp)
+ thread_plan_sp->SetPrivate (orig_plan_private);
+ return_value = eExecutionCompleted;
+ }
+ else
+ {
+ if (log)
+ log->PutCString ("Process::RunThreadPlan(): thread plan didn't successfully complete.");
+
+ return_value = eExecutionInterrupted;
+ }
}
- }
- }
- break;
+ }
+ break;
- case lldb::eStateCrashed:
- if (log)
- log->PutCString ("Process::RunThreadPlan(): execution crashed.");
- return_value = eExecutionInterrupted;
- break;
+ case lldb::eStateCrashed:
+ if (log)
+ log->PutCString ("Process::RunThreadPlan(): execution crashed.");
+ return_value = eExecutionInterrupted;
+ break;
- case lldb::eStateRunning:
- do_resume = false;
- keep_going = true;
- break;
+ case lldb::eStateRunning:
+ do_resume = false;
+ keep_going = true;
+ break;
- default:
- if (log)
- log->Printf("Process::RunThreadPlan(): execution stopped with unexpected state: %s.", StateAsCString(stop_state));
-
- if (stop_state == eStateExited)
- event_to_broadcast_sp = event_sp;
-
- errors.Printf ("Execution stopped with unexpected state.");
- return_value = eExecutionInterrupted;
- break;
+ default:
+ if (log)
+ log->Printf("Process::RunThreadPlan(): execution stopped with unexpected state: %s.", StateAsCString(stop_state));
+
+ if (stop_state == eStateExited)
+ event_to_broadcast_sp = event_sp;
+
+ errors.Printf ("Execution stopped with unexpected state.");
+ return_value = eExecutionInterrupted;
+ break;
+ }
}
+
if (keep_going)
continue;
else
@@ -4499,83 +4543,92 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,
do
{
- const Process::ProcessEventData *event_data = Process::ProcessEventData::GetEventDataFromEvent (event_sp.get());
-
- if (!event_data)
+ if (!event_sp)
{
- event_explanation = "<no event data>";
+ event_explanation = "<no event>";
break;
}
-
- Process *process = event_data->GetProcessSP().get();
-
- if (!process)
+ else if (event_sp->GetType() == eBroadcastBitInterrupt)
{
- event_explanation = "<no process>";
+ event_explanation = "<user interrupt>";
break;
}
-
- ThreadList &thread_list = process->GetThreadList();
-
- uint32_t num_threads = thread_list.GetSize();
- uint32_t thread_index;
-
- ts.Printf("<%u threads> ", num_threads);
-
- for (thread_index = 0;
- thread_index < num_threads;
- ++thread_index)
+ else
{
- Thread *thread = thread_list.GetThreadAtIndex(thread_index).get();
+ const Process::ProcessEventData *event_data = Process::ProcessEventData::GetEventDataFromEvent (event_sp.get());
+
+ if (!event_data)
+ {
+ event_explanation = "<no event data>";
+ break;
+ }
- if (!thread)
+ Process *process = event_data->GetProcessSP().get();
+
+ if (!process)
{
- ts.Printf("<?> ");
- continue;
+ event_explanation = "<no process>";
+ break;
}
- ts.Printf("<0x%4.4llx ", thread->GetID());
- RegisterContext *register_context = thread->GetRegisterContext().get();
+ ThreadList &thread_list = process->GetThreadList();
- if (register_context)
- ts.Printf("[ip 0x%llx] ", register_context->GetPC());
- else
- ts.Printf("[ip unknown] ");
+ uint32_t num_threads = thread_list.GetSize();
+ uint32_t thread_index;
- lldb::StopInfoSP stop_info_sp = thread->GetStopInfo();
- if (stop_info_sp)
+ ts.Printf("<%u threads> ", num_threads);
+
+ for (thread_index = 0;
+ thread_index < num_threads;
+ ++thread_index)
{
- const char *stop_desc = stop_info_sp->GetDescription();
- if (stop_desc)
- ts.PutCString (stop_desc);
+ Thread *thread = thread_list.GetThreadAtIndex(thread_index).get();
+
+ if (!thread)
+ {
+ ts.Printf("<?> ");
+ continue;
+ }
+
+ ts.Printf("<0x%4.4llx ", thread->GetID());
+ RegisterContext *register_context = thread->GetRegisterContext().get();
+
+ if (register_context)
+ ts.Printf("[ip 0x%llx] ", register_context->GetPC());
+ else
+ ts.Printf("[ip unknown] ");
+
+ lldb::StopInfoSP stop_info_sp = thread->GetStopInfo();
+ if (stop_info_sp)
+ {
+ const char *stop_desc = stop_info_sp->GetDescription();
+ if (stop_desc)
+ ts.PutCString (stop_desc);
+ }
+ ts.Printf(">");
}
- ts.Printf(">");
+
+ event_explanation = ts.GetData();
}
-
- event_explanation = ts.GetData();
} while (0);
- if (log)
- {
- if (event_explanation)
- log->Printf("Process::RunThreadPlan(): execution interrupted: %s %s", s.GetData(), event_explanation);
- else
- log->Printf("Process::RunThreadPlan(): execution interrupted: %s", s.GetData());
- }
-
- if (discard_on_error && thread_plan_sp)
- {
- if (log)
- log->Printf ("Process::RunThreadPlan: ExecutionInterrupted - discarding thread plans up to %p.", thread_plan_sp.get());
- thread->DiscardThreadPlansUpToPlan (thread_plan_sp);
- thread_plan_sp->SetPrivate (orig_plan_private);
- }
+ if (event_explanation)
+ log->Printf("Process::RunThreadPlan(): execution interrupted: %s %s", s.GetData(), event_explanation);
else
- {
- if (log)
- log->Printf ("Process::RunThreadPlan: ExecutionInterrupted - for plan: %p not discarding.", thread_plan_sp.get());
-
- }
+ log->Printf("Process::RunThreadPlan(): execution interrupted: %s", s.GetData());
+ }
+
+ if (discard_on_error && thread_plan_sp)
+ {
+ if (log)
+ log->Printf ("Process::RunThreadPlan: ExecutionInterrupted - discarding thread plans up to %p.", thread_plan_sp.get());
+ thread->DiscardThreadPlansUpToPlan (thread_plan_sp);
+ thread_plan_sp->SetPrivate (orig_plan_private);
+ }
+ else
+ {
+ if (log)
+ log->Printf ("Process::RunThreadPlan: ExecutionInterrupted - for plan: %p not discarding.", thread_plan_sp.get());
}
}
else if (return_value == eExecutionSetupError)
diff --git a/lldb/source/Target/TargetList.cpp b/lldb/source/Target/TargetList.cpp
index 34abd43e0a6..dae859d77fa 100644
--- a/lldb/source/Target/TargetList.cpp
+++ b/lldb/source/Target/TargetList.cpp
@@ -349,7 +349,7 @@ TargetList::SendAsyncInterrupt (lldb::pid_t pid)
Process* process = target_sp->GetProcessSP().get();
if (process)
{
- process->BroadcastEvent (Process::eBroadcastBitInterrupt, NULL);
+ process->SendAsyncInterrupt();
++num_async_interrupts_sent;
}
}
diff --git a/lldb/tools/driver/Driver.cpp b/lldb/tools/driver/Driver.cpp
index ab69b24b947..9926149f3f9 100644
--- a/lldb/tools/driver/Driver.cpp
+++ b/lldb/tools/driver/Driver.cpp
@@ -1080,11 +1080,12 @@ Driver::EditLineInputReaderCallback
case eInputReaderInterrupt:
if (driver->m_io_channel_ap.get() != NULL)
{
- SBProcess process = driver->GetDebugger().GetSelectedTarget().GetProcess();
+ SBProcess process(driver->GetDebugger().GetSelectedTarget().GetProcess());
if (!driver->m_io_channel_ap->EditLineHasCharacters()
- && process.IsValid() && process.GetState() == lldb::eStateRunning)
+ && process.IsValid()
+ && (process.GetState() == lldb::eStateRunning || process.GetState() == lldb::eStateAttaching))
{
- process.Stop();
+ process.SendAsyncInterrupt ();
}
else
{
diff --git a/lldb/tools/driver/IOChannel.cpp b/lldb/tools/driver/IOChannel.cpp
index a553ff67fb6..b6d4224a790 100644
--- a/lldb/tools/driver/IOChannel.cpp
+++ b/lldb/tools/driver/IOChannel.cpp
@@ -55,7 +55,15 @@ IOChannel::EditLineHasCharacters ()
{
const LineInfo *line_info = el_line(m_edit_line);
if (line_info)
- return line_info->cursor != line_info->buffer;
+ {
+ // Sometimes we get called after the user has submitted the line, but before editline has
+ // cleared the buffer. In that case the cursor will be pointing at the newline. That's
+ // equivalent to having no characters on the line, since it has already been submitted.
+ if (*line_info->cursor == '\n')
+ return false;
+ else
+ return line_info->cursor != line_info->buffer;
+ }
else
return false;
}
OpenPOWER on IntegriCloud