<rdar://problem/12500785>
authorGreg Clayton <gclayton@apple.com>
Mon, 29 Oct 2012 20:52:08 +0000 (20:52 +0000)
committerGreg Clayton <gclayton@apple.com>
Mon, 29 Oct 2012 20:52:08 +0000 (20:52 +0000)
I tracked down a leak that could happen when detaching from a process where the lldb_private::Process objects would stay around forever. This was caused by a eStateDetached event that was queued up on the lldb_private::Process private state thread listener. Since process events contain shared pointers to the process, this is dangerous if they don't get consume or cleared as having the lldb_private::Process class contain a collection of things that have a shared pointer to yourself is obviously bad.

To fix this I modified the Process::Finalize() function to clear this list. The actual thing that was holding onto the ModuleSP and thus the static archive, was a stack frame. Since the process wasn't going away, it still had thread objects and they still had frames. I modified the Thread::Destroy() to clear the stack frames to ensure this further doesn't happen.

llvm-svn: 166964

lldb/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.h
lldb/source/Target/Process.cpp
lldb/source/Target/Thread.cpp

index 3e89307..ce245b1 100644 (file)
@@ -108,7 +108,6 @@ protected:
         uint32_t        ar_size;        // size in bytes
         uint32_t        ar_file_offset; // file offset in bytes from the beginning of the file of the object data
         uint32_t        ar_file_size;   // length of the object data
-        lldb::ObjectFileSP object_file_sp;
 
         typedef std::vector<Object>         collection;
         typedef collection::iterator        iterator;
@@ -177,7 +176,7 @@ protected:
         //----------------------------------------------------------------------
         lldb_private::ArchSpec m_arch;
         lldb_private::TimeValue m_time;
-        Object::collection  m_objects;
+        Object::collection m_objects;
         lldb_private::UniqueCStringMap<uint32_t> m_object_name_to_index_map;
     };
 
index 1f975c4..7372832 100644 (file)
@@ -973,6 +973,10 @@ Process::Process(Target &target, Listener &listener) :
     SetEventName (eBroadcastBitSTDOUT, "stdout-available");
     SetEventName (eBroadcastBitSTDERR, "stderr-available");
     
+    m_private_state_control_broadcaster.SetEventName (eBroadcastInternalStateControlStop  , "control-stop"  );
+    m_private_state_control_broadcaster.SetEventName (eBroadcastInternalStateControlPause , "control-pause" );
+    m_private_state_control_broadcaster.SetEventName (eBroadcastInternalStateControlResume, "control-resume");
+
     listener.StartListeningForEvents (this,
                                       eBroadcastBitStateChanged |
                                       eBroadcastBitInterrupt |
@@ -1055,6 +1059,19 @@ Process::Finalize()
     m_allocated_memory_cache.Clear();
     m_language_runtimes.clear();
     m_next_event_action_ap.reset();
+//#ifdef LLDB_CONFIGURATION_DEBUG
+//    StreamFile s(stdout, false);
+//    EventSP event_sp;
+//    while (m_private_state_listener.GetNextEvent(event_sp))
+//    {
+//        event_sp->Dump (&s);
+//        s.EOL();
+//    }
+//#endif
+    // We have to be very careful here as the m_private_state_listener might
+    // contain events that have ProcessSP values in them which can keep this
+    // process around forever. These events need to be cleared out.
+    m_private_state_listener.Clear();
     m_finalize_called = true;
 }
 
@@ -1550,7 +1567,10 @@ Process::SetPrivateState (StateType new_state)
                 log->Printf("Process::SetPrivateState (%s) stop_id = %u", StateAsCString(new_state), m_mod_id.GetStopID());
         }
         // Use our target to get a shared pointer to ourselves...
-        m_private_state_broadcaster.BroadcastEvent (eBroadcastBitStateChanged, new ProcessEventData (GetTarget().GetProcessSP(), new_state));
+        if (m_finalize_called && PrivateStateThreadIsValid() == false)
+            BroadcastEvent (eBroadcastBitStateChanged, new ProcessEventData (shared_from_this(), new_state));
+        else
+            m_private_state_broadcaster.BroadcastEvent (eBroadcastBitStateChanged, new ProcessEventData (shared_from_this(), new_state));
     }
     else
     {
@@ -3950,7 +3970,7 @@ Process::AppendSTDOUT (const char * s, size_t len)
 {
     Mutex::Locker locker (m_stdio_communication_mutex);
     m_stdout_data.append (s, len);
-    BroadcastEventIfUnique (eBroadcastBitSTDOUT, new ProcessEventData (GetTarget().GetProcessSP(), GetState()));
+    BroadcastEventIfUnique (eBroadcastBitSTDOUT, new ProcessEventData (shared_from_this(), GetState()));
 }
 
 void
@@ -3958,7 +3978,7 @@ Process::AppendSTDERR (const char * s, size_t len)
 {
     Mutex::Locker locker (m_stdio_communication_mutex);
     m_stderr_data.append (s, len);
-    BroadcastEventIfUnique (eBroadcastBitSTDERR, new ProcessEventData (GetTarget().GetProcessSP(), GetState()));
+    BroadcastEventIfUnique (eBroadcastBitSTDERR, new ProcessEventData (shared_from_this(), GetState()));
 }
 
 //------------------------------------------------------------------
index 39157dd..a7f3864 100644 (file)
@@ -279,11 +279,16 @@ Thread::~Thread()
 void 
 Thread::DestroyThread ()
 {
+    m_destroy_called = true;
     m_plan_stack.clear();
     m_discarded_plan_stack.clear();
     m_completed_plan_stack.clear();
     m_actual_stop_info_sp.reset();
-    m_destroy_called = true;
+    m_reg_context_sp.reset();
+    m_unwinder_ap.reset();
+    Mutex::Locker locker(m_frame_mutex);
+    m_curr_frames_sp.reset();
+    m_prev_frames_sp.reset();
 }
 
 void