<rdar://problem/12500785>

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
This commit is contained in:
Greg Clayton 2012-10-29 20:52:08 +00:00
parent c2cccd795f
commit 35a4cc5ea7
3 changed files with 30 additions and 6 deletions

View 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;
};

View 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()));
}
//------------------------------------------------------------------

View 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