Rework how the API mutex is acquired when filling out an ExecutionContext from an ExecutionContextRef,
particularly in the SBThread & SBFrame interfaces.  Instead of filling the whole context & then getting
the API mutex, we now get only the target, acquire the API mutex from it, then fill out the rest of the
context.  This removes a race condition where you get a ThreadSP, then wait on the API mutex while another
command Destroy's the Thread you've just gotten.
Also fixed the ExecutionContextRef::Get*SP calls so they don't return invalid objects.
Also fixed the ExecutionContext::Has*Scope calls so they don't claim to have a scope if the object representing
that scope has been destroyed.
Also fixed a think-o in Thread::IsValid which was causing it to return the opposite of the desired value.

<rdar://problem/11995490>


git-svn-id: https://llvm.org/svn/llvm-project/lldb/trunk@162401 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/source/Target/ExecutionContext.cpp b/source/Target/ExecutionContext.cpp
index 300e879..ae3fc20 100644
--- a/source/Target/ExecutionContext.cpp
+++ b/source/Target/ExecutionContext.cpp
@@ -169,6 +169,40 @@
     }
 }
 
+ExecutionContext::ExecutionContext (const ExecutionContextRef *exe_ctx_ref_ptr, Mutex::Locker &locker) :
+    m_target_sp (),
+    m_process_sp (),
+    m_thread_sp (),
+    m_frame_sp ()
+{
+    if (exe_ctx_ref_ptr)
+    {
+        m_target_sp  = exe_ctx_ref_ptr->GetTargetSP();
+        if (m_target_sp)
+        {
+            locker.Lock(m_target_sp->GetAPIMutex());
+            m_process_sp = exe_ctx_ref_ptr->GetProcessSP();
+            m_thread_sp = exe_ctx_ref_ptr->GetThreadSP();
+            m_frame_sp = exe_ctx_ref_ptr->GetFrameSP();
+        }
+    }
+}
+
+ExecutionContext::ExecutionContext (const ExecutionContextRef &exe_ctx_ref, Mutex::Locker &locker) :
+    m_target_sp (exe_ctx_ref.GetTargetSP()),
+    m_process_sp (),
+    m_thread_sp (),
+    m_frame_sp ()
+{
+    if (m_target_sp)
+    {
+        locker.Lock(m_target_sp->GetAPIMutex());
+        m_process_sp = exe_ctx_ref.GetProcessSP();
+        m_thread_sp  = exe_ctx_ref.GetThreadSP();
+        m_frame_sp   = exe_ctx_ref.GetFrameSP();
+    }
+}
+
 ExecutionContext::ExecutionContext (ExecutionContextScope *exe_scope_ptr) :
     m_target_sp (),
     m_process_sp (),
@@ -459,6 +493,32 @@
     return !(*this == rhs);
 }
 
+bool
+ExecutionContext::HasTargetScope () const
+{
+    return ((bool) m_target_sp
+            && m_target_sp->IsValid());
+}
+
+bool
+ExecutionContext::HasProcessScope () const
+{
+    return (HasTargetScope()
+            && ((bool) m_process_sp && m_process_sp->IsValid()));
+}
+
+bool
+ExecutionContext::HasThreadScope () const
+{
+    return (HasProcessScope()
+           && ((bool) m_thread_sp && m_thread_sp->IsValid()));
+}
+
+bool
+ExecutionContext::HasFrameScope () const
+{
+    return HasThreadScope() && m_frame_sp;
+}
 
 ExecutionContextRef::ExecutionContextRef() :
     m_target_wp (),
@@ -703,11 +763,29 @@
         Clear();
 }
 
+lldb::TargetSP
+ExecutionContextRef::GetTargetSP () const
+{
+    lldb::TargetSP target_sp(m_target_wp.lock());
+    if (target_sp && !target_sp->IsValid())
+        target_sp.reset();
+    return target_sp;
+}
+
+lldb::ProcessSP
+ExecutionContextRef::GetProcessSP () const
+{
+    lldb::ProcessSP process_sp(m_process_wp.lock());
+    if (process_sp && !process_sp->IsValid())
+        process_sp.reset();
+    return process_sp;
+}
 
 lldb::ThreadSP
 ExecutionContextRef::GetThreadSP () const
 {
     lldb::ThreadSP thread_sp (m_thread_wp.lock());
+    
     if (m_tid != LLDB_INVALID_THREAD_ID)
     {
         // We check if the thread has been destroyed in cases where clients
@@ -716,13 +794,20 @@
         if (!thread_sp || !thread_sp->IsValid())
         {
             lldb::ProcessSP process_sp(GetProcessSP());
-            if (process_sp)
+            if (process_sp && process_sp->IsValid())
             {
                 thread_sp = process_sp->GetThreadList().FindThreadByID(m_tid);
                 m_thread_wp = thread_sp;
             }
         }
     }
+    
+    // Check that we aren't about to return an invalid thread sp.  We might return a NULL thread_sp,
+    // but don't return an invalid one.
+    
+    if (thread_sp && !thread_sp->IsValid())
+        thread_sp.reset();
+    
     return thread_sp;
 }
 
@@ -738,6 +823,12 @@
             frame_sp = thread_sp->GetFrameWithStackID (m_stack_id);
             m_frame_wp = frame_sp;
         }
+        else
+        {
+            // If the thread that this frame was supposed to belong to is not valid, then
+            // return a NULL frame_sp.
+            frame_sp.reset();
+        }
     }
     return frame_sp;
 }