forked from OSchip/llvm-project
Work around some problems destroying a process with older debugservers.
rdar://problem/11359989 llvm-svn: 159697
This commit is contained in:
parent
ef285b4c22
commit
43c555dfcd
|
|
@ -775,6 +775,13 @@ public:
|
|||
{
|
||||
return m_destroy_called;
|
||||
}
|
||||
|
||||
// When you implement this method, make sure you don't overwrite the m_actual_stop_info if it claims to be
|
||||
// valid. The stop info may be a "checkpointed and restored" stop info, so if it is still around it is right
|
||||
// even if you have not calculated this yourself, or if it disagrees with what you might have calculated.
|
||||
virtual lldb::StopInfoSP
|
||||
GetPrivateStopReason () = 0;
|
||||
|
||||
protected:
|
||||
|
||||
friend class ThreadPlan;
|
||||
|
|
@ -796,12 +803,6 @@ protected:
|
|||
|
||||
ThreadPlan *GetPreviousPlan (ThreadPlan *plan);
|
||||
|
||||
// When you implement this method, make sure you don't overwrite the m_actual_stop_info if it claims to be
|
||||
// valid. The stop info may be a "checkpointed and restored" stop info, so if it is still around it is right
|
||||
// even if you have not calculated this yourself, or if it disagrees with what you might have calculated.
|
||||
virtual lldb::StopInfoSP
|
||||
GetPrivateStopReason () = 0;
|
||||
|
||||
typedef std::vector<lldb::ThreadPlanSP> plan_stack;
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@
|
|||
// Project includes
|
||||
#include "lldb/Host/Host.h"
|
||||
#include "Plugins/Process/Utility/InferiorCallPOSIX.h"
|
||||
#include "Plugins/Platform/MacOSX/PlatformRemoteiOS.h"
|
||||
#include "Utility/StringExtractorGDBRemote.h"
|
||||
#include "GDBRemoteRegisterContext.h"
|
||||
#include "ProcessGDBRemote.h"
|
||||
|
|
@ -175,7 +176,8 @@ ProcessGDBRemote::ProcessGDBRemote(Target& target, Listener &listener) :
|
|||
m_max_memory_size (512),
|
||||
m_addr_to_mmap_size (),
|
||||
m_thread_create_bp_sp (),
|
||||
m_waiting_for_attach (false)
|
||||
m_waiting_for_attach (false),
|
||||
m_destroy_tried_resuming (false)
|
||||
{
|
||||
m_async_broadcaster.SetEventName (eBroadcastBitAsyncThreadShouldExit, "async thread should exit");
|
||||
m_async_broadcaster.SetEventName (eBroadcastBitAsyncContinue, "async thread continue");
|
||||
|
|
@ -1689,6 +1691,7 @@ ProcessGDBRemote::DoDetach()
|
|||
return error;
|
||||
}
|
||||
|
||||
|
||||
Error
|
||||
ProcessGDBRemote::DoDestroy ()
|
||||
{
|
||||
|
|
@ -1697,6 +1700,110 @@ ProcessGDBRemote::DoDestroy ()
|
|||
if (log)
|
||||
log->Printf ("ProcessGDBRemote::DoDestroy()");
|
||||
|
||||
// There is a bug in older iOS debugservers where they don't shut down the process
|
||||
// they are debugging properly. If the process is sitting at a breakpoint or an exception,
|
||||
// this can cause problems with restarting. So we check to see if any of our threads are stopped
|
||||
// at a breakpoint, and if so we remove all the breakpoints, resume the process, and THEN
|
||||
// destroy it again.
|
||||
//
|
||||
// Note, we don't have a good way to test the version of debugserver, but I happen to know that
|
||||
// the set of all the iOS debugservers which don't support GetThreadSuffixSupported() and that of
|
||||
// the debugservers with this bug are equal. There really should be a better way to test this!
|
||||
//
|
||||
// We also use m_destroy_tried_resuming to make sure we only do this once, if we resume and then halt and
|
||||
// get called here to destroy again and we're still at a breakpoint or exception, then we should
|
||||
// just do the straight-forward kill.
|
||||
//
|
||||
// And of course, if we weren't able to stop the process by the time we get here, it isn't
|
||||
// necessary (or helpful) to do any of this.
|
||||
|
||||
if (!m_gdb_comm.GetThreadSuffixSupported() && m_public_state.GetValue() != eStateRunning)
|
||||
{
|
||||
PlatformSP platform_sp = GetTarget().GetPlatform();
|
||||
|
||||
// FIXME: These should be ConstStrings so we aren't doing strcmp'ing.
|
||||
if (platform_sp
|
||||
&& platform_sp->GetName()
|
||||
&& strcmp (platform_sp->GetName(), PlatformRemoteiOS::GetShortPluginNameStatic()) == 0)
|
||||
{
|
||||
if (m_destroy_tried_resuming)
|
||||
{
|
||||
if (log)
|
||||
log->PutCString ("ProcessGDBRemote::DoDestroy()Tried resuming to destroy once already, not doing it again.");
|
||||
}
|
||||
else
|
||||
{
|
||||
// At present, the plans are discarded and the breakpoints disabled Process::Destroy,
|
||||
// but we really need it to happen here and it doesn't matter if we do it twice.
|
||||
m_thread_list.DiscardThreadPlans();
|
||||
DisableAllBreakpointSites();
|
||||
|
||||
bool stop_looks_like_crash = false;
|
||||
ThreadList &threads = GetThreadList();
|
||||
|
||||
{
|
||||
Mutex::Locker(threads.GetMutex());
|
||||
|
||||
size_t num_threads = threads.GetSize();
|
||||
for (size_t i = 0; i < num_threads; i++)
|
||||
{
|
||||
ThreadSP thread_sp = threads.GetThreadAtIndex(i);
|
||||
StopInfoSP stop_info_sp = thread_sp->GetPrivateStopReason();
|
||||
StopReason reason = eStopReasonInvalid;
|
||||
if (stop_info_sp)
|
||||
reason = stop_info_sp->GetStopReason();
|
||||
if (reason == eStopReasonBreakpoint
|
||||
|| reason == eStopReasonException)
|
||||
{
|
||||
if (log)
|
||||
log->Printf ("ProcessGDBRemote::DoDestroy() - thread: %lld stopped with reason: %s.",
|
||||
thread_sp->GetID(),
|
||||
stop_info_sp->GetDescription());
|
||||
stop_looks_like_crash = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (stop_looks_like_crash)
|
||||
{
|
||||
if (log)
|
||||
log->PutCString ("ProcessGDBRemote::DoDestroy() - Stopped at a breakpoint, continue and then kill.");
|
||||
m_destroy_tried_resuming = true;
|
||||
|
||||
// If we are going to run again before killing, it would be good to suspend all the threads
|
||||
// before resuming so they won't get into more trouble. Sadly, for the threads stopped with
|
||||
// the breakpoint or exception, the exception doesn't get cleared if it is suspended, so we do
|
||||
// have to run the risk of letting those threads proceed a bit.
|
||||
|
||||
{
|
||||
Mutex::Locker(threads.GetMutex());
|
||||
|
||||
size_t num_threads = threads.GetSize();
|
||||
for (size_t i = 0; i < num_threads; i++)
|
||||
{
|
||||
ThreadSP thread_sp = threads.GetThreadAtIndex(i);
|
||||
StopInfoSP stop_info_sp = thread_sp->GetPrivateStopReason();
|
||||
StopReason reason = eStopReasonInvalid;
|
||||
if (stop_info_sp)
|
||||
reason = stop_info_sp->GetStopReason();
|
||||
if (reason != eStopReasonBreakpoint
|
||||
&& reason != eStopReasonException)
|
||||
{
|
||||
if (log)
|
||||
log->Printf ("ProcessGDBRemote::DoDestroy() - Suspending thread: %lld before running.",
|
||||
thread_sp->GetID());
|
||||
thread_sp->SetResumeState(eStateSuspended);
|
||||
}
|
||||
}
|
||||
}
|
||||
Resume ();
|
||||
return Destroy();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Interrupt if our inferior is running...
|
||||
int exit_status = SIGABRT;
|
||||
std::string exit_string;
|
||||
|
|
|
|||
|
|
@ -321,6 +321,7 @@ protected:
|
|||
MMapMap m_addr_to_mmap_size;
|
||||
lldb::BreakpointSP m_thread_create_bp_sp;
|
||||
bool m_waiting_for_attach;
|
||||
bool m_destroy_tried_resuming;
|
||||
|
||||
bool
|
||||
StartAsyncThread ();
|
||||
|
|
|
|||
|
|
@ -1621,6 +1621,11 @@ void
|
|||
Process::DisableAllBreakpointSites ()
|
||||
{
|
||||
m_breakpoint_site_list.SetEnabledForAll (false);
|
||||
size_t num_sites = m_breakpoint_site_list.GetSize();
|
||||
for (size_t i = 0; i < num_sites; i++)
|
||||
{
|
||||
DisableBreakpoint (m_breakpoint_site_list.GetByIndex(i).get());
|
||||
}
|
||||
}
|
||||
|
||||
Error
|
||||
|
|
|
|||
Loading…
Reference in New Issue