[Lldb-commits] [lldb] r159697 - in /lldb/trunk: include/lldb/Target/Thread.h source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp source/Plugins/Process/gdb-remote/ProcessGDBRemote.h source/Target/Process.cpp

Jim Ingham jingham at apple.com
Tue Jul 3 17:35:43 PDT 2012


Author: jingham
Date: Tue Jul  3 19:35:43 2012
New Revision: 159697

URL: http://llvm.org/viewvc/llvm-project?rev=159697&view=rev
Log:
Work around some problems destroying a process with older debugservers.

rdar://problem/11359989

Modified:
    lldb/trunk/include/lldb/Target/Thread.h
    lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
    lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
    lldb/trunk/source/Target/Process.cpp

Modified: lldb/trunk/include/lldb/Target/Thread.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/Thread.h?rev=159697&r1=159696&r2=159697&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Target/Thread.h (original)
+++ lldb/trunk/include/lldb/Target/Thread.h Tue Jul  3 19:35:43 2012
@@ -775,6 +775,13 @@
     {
         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 @@
 
     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

Modified: lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp?rev=159697&r1=159696&r2=159697&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp (original)
+++ lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp Tue Jul  3 19:35:43 2012
@@ -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 @@
     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 @@
     return error;
 }
 
+
 Error
 ProcessGDBRemote::DoDestroy ()
 {
@@ -1697,6 +1700,110 @@
     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;

Modified: lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h?rev=159697&r1=159696&r2=159697&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h (original)
+++ lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h Tue Jul  3 19:35:43 2012
@@ -321,6 +321,7 @@
     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 ();

Modified: lldb/trunk/source/Target/Process.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/Process.cpp?rev=159697&r1=159696&r2=159697&view=diff
==============================================================================
--- lldb/trunk/source/Target/Process.cpp (original)
+++ lldb/trunk/source/Target/Process.cpp Tue Jul  3 19:35:43 2012
@@ -1621,6 +1621,11 @@
 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





More information about the lldb-commits mailing list