diff options
Diffstat (limited to 'lldb/source')
-rw-r--r-- | lldb/source/API/SBProcess.cpp | 10 | ||||
-rw-r--r-- | lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp | 16 | ||||
-rw-r--r-- | lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h | 12 | ||||
-rw-r--r-- | lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp | 124 | ||||
-rw-r--r-- | lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h | 9 | ||||
-rw-r--r-- | lldb/source/Target/Process.cpp | 55 |
6 files changed, 172 insertions, 54 deletions
diff --git a/lldb/source/API/SBProcess.cpp b/lldb/source/API/SBProcess.cpp index bfdf8578b1c..2a3d415a7b9 100644 --- a/lldb/source/API/SBProcess.cpp +++ b/lldb/source/API/SBProcess.cpp @@ -421,11 +421,12 @@ SBProcess::Continue () SBError SBProcess::Destroy () { - Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex()); - SBError sb_error; if (m_opaque_sp) + { + Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex()); sb_error.SetError(m_opaque_sp->Destroy()); + } else sb_error.SetErrorString ("SBProcess is invalid"); @@ -434,7 +435,10 @@ SBProcess::Destroy () { SBStream sstr; sb_error.GetDescription (sstr); - log->Printf ("SBProcess(%p)::Destroy () => SBError (%p): %s", m_opaque_sp.get(), sb_error.get(), sstr.GetData()); + log->Printf ("SBProcess(%p)::Destroy () => SBError (%p): %s", + m_opaque_sp.get(), + sb_error.get(), + sstr.GetData()); } return sb_error; diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp index 38b823f77aa..a779db25756 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp @@ -511,6 +511,18 @@ GDBRemoteCommunication::SendInterrupt return false; } +bool +GDBRemoteCommunication::WaitForNotRunning (const TimeValue *timeout_ptr) +{ + return m_public_is_running.WaitForValueEqualTo (false, timeout_ptr, NULL); +} + +bool +GDBRemoteCommunication::WaitForNotRunningPrivate (const TimeValue *timeout_ptr) +{ + return m_private_is_running.WaitForValueEqualTo (false, timeout_ptr, NULL); +} + size_t GDBRemoteCommunication::WaitForPacket (StringExtractorGDBRemote &response, uint32_t timeout_seconds) { @@ -522,14 +534,14 @@ GDBRemoteCommunication::WaitForPacket (StringExtractorGDBRemote &response, uint3 } size_t -GDBRemoteCommunication::WaitForPacket (StringExtractorGDBRemote &response, TimeValue* timeout_time_ptr) +GDBRemoteCommunication::WaitForPacket (StringExtractorGDBRemote &response, const TimeValue* timeout_time_ptr) { Mutex::Locker locker(m_sequence_mutex); return WaitForPacketNoLock (response, timeout_time_ptr); } size_t -GDBRemoteCommunication::WaitForPacketNoLock (StringExtractorGDBRemote &response, TimeValue* timeout_time_ptr) +GDBRemoteCommunication::WaitForPacketNoLock (StringExtractorGDBRemote &response, const TimeValue* timeout_time_ptr) { bool checksum_error = false; response.Clear (); diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h index bcbaeb5ebd9..3ebabeb7085 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h @@ -81,7 +81,7 @@ public: // wait indefinitely. size_t WaitForPacket (StringExtractorGDBRemote &response, - lldb_private::TimeValue* timeout); + const lldb_private::TimeValue* timeout); char GetAck (uint32_t timeout_seconds); @@ -222,7 +222,10 @@ public: { return m_public_is_running.GetValue(); } - + + bool + WaitForNotRunning (const lldb_private::TimeValue *timeout_ptr); + bool GetHostInfo (uint32_t timeout_seconds); @@ -256,7 +259,10 @@ protected: size_t WaitForPacketNoLock (StringExtractorGDBRemote &response, - lldb_private::TimeValue* timeout_time_ptr); + const lldb_private::TimeValue* timeout_ptr); + + bool + WaitForNotRunningPrivate (const lldb_private::TimeValue *timeout_ptr); //------------------------------------------------------------------ // Classes that inherit from GDBRemoteCommunication can see and modify these diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp index 5abe070f962..fe4e06820fc 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp @@ -1157,7 +1157,13 @@ ProcessGDBRemote::DoHalt (bool &caused_stop) } Error -ProcessGDBRemote::WillDetach () +ProcessGDBRemote::InterruptIfRunning +( + bool discard_thread_plans, + bool catch_stop_event, + bool resume_private_state_thread, + EventSP &stop_event_sp +) { Error error; @@ -1166,30 +1172,54 @@ ProcessGDBRemote::WillDetach () bool timed_out = false; bool sent_interrupt = false; Mutex::Locker locker; - PausePrivateStateThread(); - m_thread_list.DiscardThreadPlans(); - m_debugserver_pid = LLDB_INVALID_PROCESS_ID; - if (!m_gdb_comm.SendInterrupt (locker, 2, sent_interrupt, timed_out)) + + if (catch_stop_event) + PausePrivateStateThread(); + + if (discard_thread_plans) + m_thread_list.DiscardThreadPlans(); + + //m_debugserver_pid = LLDB_INVALID_PROCESS_ID; + if (!m_gdb_comm.SendInterrupt (locker, 1, sent_interrupt, timed_out)) { if (timed_out) error.SetErrorString("timed out sending interrupt packet"); else error.SetErrorString("unknown error sending interrupt packet"); - ResumePrivateStateThread(); + if (catch_stop_event) + ResumePrivateStateThread(); + return error; } - TimeValue timeout_time; - timeout_time = TimeValue::Now(); - timeout_time.OffsetWithSeconds(2); + + + if (catch_stop_event) + { + TimeValue timeout_time; + timeout_time = TimeValue::Now(); + timeout_time.OffsetWithSeconds(1); + StateType state = WaitForProcessStopPrivate (&timeout_time, stop_event_sp); - EventSP event_sp; - StateType state = WaitForStateChangedEventsPrivate (&timeout_time, event_sp); - if (state != eStateStopped) - error.SetErrorString("unable to stop target"); + if (state == eStateInvalid) + error.SetErrorString("unable to verify target stopped"); + } + + if (catch_stop_event && resume_private_state_thread) + ResumePrivateStateThread(); } return error; } Error +ProcessGDBRemote::WillDetach () +{ + bool discard_thread_plans = true; + bool catch_stop_event = true; + bool resume_private_state_thread = false; // DoDetach will resume the thread + EventSP event_sp; + return InterruptIfRunning (discard_thread_plans, catch_stop_event, resume_private_state_thread, event_sp); +} + +Error ProcessGDBRemote::DoDetach() { Error error; @@ -1223,6 +1253,16 @@ ProcessGDBRemote::DoDetach() } Error +ProcessGDBRemote::WillDestroy () +{ + bool discard_thread_plans = true; + bool catch_stop_event = true; + bool resume_private_state_thread = true; + EventSP event_sp; + return InterruptIfRunning (discard_thread_plans, catch_stop_event, resume_private_state_thread, event_sp); +} + +Error ProcessGDBRemote::DoDestroy () { Error error; @@ -1233,10 +1273,40 @@ ProcessGDBRemote::DoDestroy () // Interrupt if our inferior is running... if (m_gdb_comm.IsConnected()) { - // Don't get a response when killing our - m_gdb_comm.SendPacket ("k", 1); + m_continue_packet.Clear(); + m_continue_packet.Printf("k"); + Listener listener ("gdb-remote.kill-packet-sent"); + if (listener.StartListeningForEvents (&m_gdb_comm, GDBRemoteCommunication::eBroadcastBitRunPacketSent)) + { + EventSP event_sp; + TimeValue timeout; + timeout = TimeValue::Now(); + timeout.OffsetWithSeconds (1); + m_async_broadcaster.BroadcastEvent (eBroadcastBitAsyncContinue, new EventDataBytes (m_continue_packet.GetData(), m_continue_packet.GetSize())); + + // Wait for the async thread to send the "k" packet + if (listener.WaitForEvent (&timeout, event_sp)) + { + if (log) + log->Printf ("ProcessGDBRemote::DoDestroy() got confirmation the \"k\" packet was sent"); + } + else + { + if (log) + log->Printf ("ProcessGDBRemote::DoDestroy() timed out waiting for \"k\" packet to be sent"); + error.SetErrorString("Resume timed out."); + } + + // Wait for the async thread to exit which will indicate we stopped. + // Hopefully the stop will be a process exited state since we are + // asking the process to go away. + if (!m_gdb_comm.WaitForNotRunning (&timeout)) + { + if (log) + log->Printf ("ProcessGDBRemote::DoDestroy() timed out waiting for \"k\" stop reply packet"); + } + } } - StopAsyncThread (); m_gdb_comm.StopReadThread(); KillDebugserverProcess (); @@ -1851,14 +1921,14 @@ ProcessGDBRemote::StartDebugserverProcess log->Printf("%s arguments:\n%s", debugserver_args.GetArgumentAtIndex(0), strm.GetData()); } - error.SetError(::posix_spawnp (&m_debugserver_pid, - debugserver_path, - file_actions_err.Success() ? &file_actions : NULL, - &attr, - debugserver_args.GetArgumentVector(), - (char * const*)inferior_envp), - eErrorTypePOSIX); - + error.SetError (::posix_spawnp (&m_debugserver_pid, + debugserver_path, + file_actions_err.Success() ? &file_actions : NULL, + &attr, + debugserver_args.GetArgumentVector(), + (char * const*)inferior_envp), + eErrorTypePOSIX); + ::posix_spawnattr_destroy (&attr); @@ -1907,7 +1977,11 @@ ProcessGDBRemote::MonitorDebugserverProcess // debugserver that we are tracking... ProcessGDBRemote *process = (ProcessGDBRemote *)callback_baton; - + + LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); + if (log) + log->Printf ("ProcessGDBRemote::MonitorDebugserverProcess (baton=%p, pid=%i, signo=%i (0x%x), exit_status=%i)", callback_baton, debugserver_pid, signo, signo, exit_status); + if (process) { // Sleep for a half a second to make sure our inferior process has diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h index ebb4cca23d4..d8a2cebbd33 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h +++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h @@ -149,6 +149,9 @@ public: DoSignal (int signal); virtual lldb_private::Error + WillDestroy (); + + virtual lldb_private::Error DoDestroy (); virtual void @@ -382,6 +385,12 @@ protected: const char *bytes, size_t bytes_len); + lldb_private::Error + InterruptIfRunning (bool discard_thread_plans, + bool catch_stop_event, + bool resume_private_state_thread, + lldb::EventSP &stop_event_sp); + private: //------------------------------------------------------------------ // For ProcessGDBRemote only diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp index 90ea0b6cb18..c3b9dfbdd23 100644 --- a/lldb/source/Target/Process.cpp +++ b/lldb/source/Target/Process.cpp @@ -452,17 +452,22 @@ Process::WaitForStateChangedEventsPrivate (const TimeValue *timeout, EventSP &ev log->Printf ("Process::%s (timeout = %p, event_sp)...", __FUNCTION__, timeout); StateType state = eStateInvalid; - if (m_private_state_listener.WaitForEventForBroadcasterWithType(timeout, - &m_private_state_broadcaster, - eBroadcastBitStateChanged, - event_sp)) + if (m_private_state_listener.WaitForEventForBroadcasterWithType (timeout, + &m_private_state_broadcaster, + eBroadcastBitStateChanged, + event_sp)) 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 // log we got above invalid. if (log) - log->Printf ("Process::%s (timeout = %p, event_sp) => %s", __FUNCTION__, timeout, StateAsCString(state)); + { + if (state == eStateInvalid) + log->Printf ("Process::%s (timeout = %p, event_sp) => TIMEOUT", __FUNCTION__, timeout); + else + log->Printf ("Process::%s (timeout = %p, event_sp) => %s", __FUNCTION__, timeout, StateAsCString(state)); + } return state; } @@ -547,21 +552,23 @@ Process::GetExitDescription () return NULL; } -void +bool Process::SetExitStatus (int status, const char *cstr) { - if (m_private_state.GetValue() != eStateExited) - { - m_exit_status = status; - if (cstr) - m_exit_string = cstr; - else - m_exit_string.clear(); + // We were already in the exited state + if (m_private_state.GetValue() == eStateExited) + return false; + + m_exit_status = status; + if (cstr) + m_exit_string = cstr; + else + m_exit_string.clear(); - DidExit (); + DidExit (); - SetPrivateState (eStateExited); - } + SetPrivateState (eStateExited); + return true; } // This static callback can be used to watch for local child processes on @@ -1425,11 +1432,17 @@ Process::WaitForProcessStopPrivate (const TimeValue *timeout, EventSP &event_sp) // call DidLaunch: while (1) { - // FIXME: Might want to put a timeout in here: - state = WaitForStateChangedEventsPrivate (NULL, event_sp); - if (state == eStateStopped || state == eStateCrashed || state == eStateExited) + event_sp.reset(); + state = WaitForStateChangedEventsPrivate (timeout, event_sp); + + if (StateIsStoppedState(state)) break; - else + + // If state is invalid, then we timed out + if (state == eStateInvalid) + break; + + if (event_sp) HandlePrivateEvent (event_sp); } return state; @@ -1744,7 +1757,7 @@ Process::Halt () // Wait for 2 seconds for the process to stop. TimeValue timeout_time; timeout_time = TimeValue::Now(); - timeout_time.OffsetWithSeconds(2); + timeout_time.OffsetWithSeconds(1); StateType state = WaitForStateChangedEventsPrivate (&timeout_time, event_sp); if (state == eStateInvalid) |