summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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