summaryrefslogtreecommitdiffstats
path: root/lldb/source/Target/Process.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/source/Target/Process.cpp')
-rw-r--r--lldb/source/Target/Process.cpp203
1 files changed, 119 insertions, 84 deletions
diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp
index 9538299c2a7..9f5a63ae9ce 100644
--- a/lldb/source/Target/Process.cpp
+++ b/lldb/source/Target/Process.cpp
@@ -237,7 +237,8 @@ Process::Process(Target &target, Listener &listener) :
m_stdio_communication ("process.stdio"),
m_stdio_communication_mutex (Mutex::eMutexTypeRecursive),
m_stdout_data (),
- m_memory_cache ()
+ m_memory_cache (),
+ m_next_event_action(NULL)
{
UpdateInstanceName();
@@ -273,6 +274,8 @@ Process::~Process()
LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
if (log)
log->Printf ("%p Process::~Process()", this);
+ if (m_next_event_action)
+ SetNextEventAction(NULL);
StopPrivateStateThread();
}
@@ -1583,23 +1586,18 @@ Process::Launch
return error;
}
-Error
-Process::CompleteAttach ()
+Process::NextEventAction::EventActionResult
+Process::AttachCompletionHandler::PerformAction (lldb::EventSP &event_sp)
{
- Error error;
-
- if (GetID() == LLDB_INVALID_PROCESS_ID)
- {
- error.SetErrorString("no process");
- }
-
- EventSP event_sp;
- StateType state = WaitForProcessStopPrivate(NULL, event_sp);
- if (state == eStateStopped || state == eStateCrashed)
+ StateType state = ProcessEventData::GetStateFromEvent (event_sp.get());
+ switch (state)
{
- DidAttach ();
+ case eStateStopped:
+ case eStateCrashed:
+ {
+ m_process->DidAttach ();
// Figure out which one is the executable, and set that in our target:
- ModuleList &modules = GetTarget().GetImages();
+ ModuleList &modules = m_process->GetTarget().GetImages();
size_t num_modules = modules.GetSize();
for (int i = 0; i < num_modules; i++)
@@ -1607,31 +1605,37 @@ Process::CompleteAttach ()
ModuleSP module_sp = modules.GetModuleAtIndex(i);
if (module_sp->IsExecutable())
{
- ModuleSP exec_module = GetTarget().GetExecutableModule();
+ ModuleSP exec_module = m_process->GetTarget().GetExecutableModule();
if (!exec_module || exec_module != module_sp)
{
- GetTarget().SetExecutableModule (module_sp, false);
+ m_process->GetTarget().SetExecutableModule (module_sp, false);
}
break;
}
}
-
- // This delays passing the stopped event to listeners till DidLaunch gets
- // a chance to complete...
- HandlePrivateEvent(event_sp);
- StartPrivateStateThread();
- }
- else
- {
- // We exited while trying to launch somehow. Don't call DidLaunch as that's
- // not likely to work, and return an invalid pid.
- if (state == eStateExited)
- HandlePrivateEvent (event_sp);
- error.SetErrorStringWithFormat("invalid state after attach: %s",
- lldb_private::StateAsCString(state));
+ return eEventActionSuccess;
+ }
+ break;
+ default:
+ case eStateExited:
+ case eStateInvalid:
+ m_exit_string.assign ("No valid Process");
+ return eEventActionExit;
+ break;
}
- return error;
+}
+
+Process::NextEventAction::EventActionResult
+Process::AttachCompletionHandler::HandleBeingInterrupted()
+{
+ return eEventActionSuccess;
+}
+
+const char *
+Process::AttachCompletionHandler::GetExitString ()
+{
+ return m_exit_string.c_str();
}
Error
@@ -1660,7 +1664,8 @@ Process::Attach (lldb::pid_t attach_pid)
error = DoAttachToProcessWithID (attach_pid);
if (error.Success())
{
- error = CompleteAttach();
+ SetNextEventAction(new Process::AttachCompletionHandler(this));
+ StartPrivateStateThread();
}
else
{
@@ -1717,7 +1722,8 @@ Process::Attach (const char *process_name, bool wait_for_launch)
}
else
{
- error = CompleteAttach();
+ SetNextEventAction(new Process::AttachCompletionHandler(this));
+ StartPrivateStateThread();
}
}
return error;
@@ -1769,73 +1775,82 @@ Process::Resume ()
Error
Process::Halt ()
{
- Error error (WillHalt());
+ // Pause our private state thread so we can ensure no one else eats
+ // the stop event out from under us.
+ PausePrivateStateThread();
+
+ EventSP event_sp;
+ Error error;
- if (error.Success())
+ if (m_public_state.GetValue() == eStateAttaching)
{
+ SetExitStatus(SIGKILL, "Cancelled async attach.");
+ }
+ else
+ {
+ error = WillHalt();
- bool caused_stop = false;
- EventSP event_sp;
-
- // Pause our private state thread so we can ensure no one else eats
- // the stop event out from under us.
- PausePrivateStateThread();
-
- // Ask the process subclass to actually halt our process
- error = DoHalt(caused_stop);
if (error.Success())
{
- // If "caused_stop" is true, then DoHalt stopped the process. If
- // "caused_stop" is false, the process was already stopped.
- // If the DoHalt caused the process to stop, then we want to catch
- // this event and set the interrupted bool to true before we pass
- // this along so clients know that the process was interrupted by
- // a halt command.
- if (caused_stop)
+
+ bool caused_stop = false;
+
+ // Ask the process subclass to actually halt our process
+ error = DoHalt(caused_stop);
+ if (error.Success())
{
- // Wait for 2 seconds for the process to stop.
- TimeValue timeout_time;
- timeout_time = TimeValue::Now();
- timeout_time.OffsetWithSeconds(1);
- StateType state = WaitForStateChangedEventsPrivate (&timeout_time, event_sp);
-
- if (state == eStateInvalid)
+ // If "caused_stop" is true, then DoHalt stopped the process. If
+ // "caused_stop" is false, the process was already stopped.
+ // If the DoHalt caused the process to stop, then we want to catch
+ // this event and set the interrupted bool to true before we pass
+ // this along so clients know that the process was interrupted by
+ // a halt command.
+ if (caused_stop)
{
- // We timeout out and didn't get a stop event...
- error.SetErrorString ("Halt timed out.");
- }
- else
- {
- if (StateIsStoppedState (state))
+ // Wait for 2 seconds for the process to stop.
+ TimeValue timeout_time;
+ timeout_time = TimeValue::Now();
+ timeout_time.OffsetWithSeconds(1);
+ StateType state = WaitForStateChangedEventsPrivate (&timeout_time, event_sp);
+
+ if (state == eStateInvalid)
{
- // We caused the process to interrupt itself, so mark this
- // as such in the stop event so clients can tell an interrupted
- // process from a natural stop
- ProcessEventData::SetInterruptedInEvent (event_sp.get(), true);
+ // We timeout out and didn't get a stop event...
+ error.SetErrorString ("Halt timed out.");
}
else
{
- LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
- if (log)
- log->Printf("Process::Halt() failed to stop, state is: %s", StateAsCString(state));
- error.SetErrorString ("Did not get stopped event after halt.");
+ if (StateIsStoppedState (state))
+ {
+ // We caused the process to interrupt itself, so mark this
+ // as such in the stop event so clients can tell an interrupted
+ // process from a natural stop
+ ProcessEventData::SetInterruptedInEvent (event_sp.get(), true);
+ }
+ else
+ {
+ LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
+ if (log)
+ log->Printf("Process::Halt() failed to stop, state is: %s", StateAsCString(state));
+ error.SetErrorString ("Did not get stopped event after halt.");
+ }
}
}
- }
- DidHalt();
+ DidHalt();
+ }
}
- // Resume our private state thread before we post the event (if any)
- ResumePrivateStateThread();
+ }
+ // Resume our private state thread before we post the event (if any)
+ ResumePrivateStateThread();
- // Post any event we might have consumed. If all goes well, we will have
- // stopped the process, intercepted the event and set the interrupted
- // bool in the event. Post it to the private event queue and that will end up
- // correctly setting the state.
- if (event_sp)
- m_private_state_broadcaster.BroadcastEvent(event_sp);
+ // Post any event we might have consumed. If all goes well, we will have
+ // stopped the process, intercepted the event and set the interrupted
+ // bool in the event. Post it to the private event queue and that will end up
+ // correctly setting the state.
+ if (event_sp)
+ m_private_state_broadcaster.BroadcastEvent(event_sp);
- }
return error;
}
@@ -2123,7 +2138,27 @@ void
Process::HandlePrivateEvent (EventSP &event_sp)
{
LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
+
const StateType new_state = Process::ProcessEventData::GetStateFromEvent(event_sp.get());
+
+ // First check to see if anybody wants a shot at this event:
+ if (m_next_event_action != NULL)
+ {
+ NextEventAction::EventActionResult action_result = m_next_event_action->PerformAction(event_sp);
+ switch (action_result)
+ {
+ case NextEventAction::eEventActionSuccess:
+ SetNextEventAction(NULL);
+ break;
+ case NextEventAction::eEventActionRetry:
+ break;
+ case NextEventAction::eEventActionExit:
+ // Handle Exiting Here...
+
+ break;
+ }
+ }
+
// See if we should broadcast this state to external clients?
const bool should_broadcast = ShouldBroadcastEvent (event_sp.get());
OpenPOWER on IntegriCloud