From 0c6d7c0a2c7e227338fe3fd7d397f210dd0b6b20 Mon Sep 17 00:00:00 2001 From: Marianne Mailhot-Sarrasin Date: Tue, 19 Apr 2016 13:21:46 +0000 Subject: [PATCH] LLDB: Fixed two race conditions when stopping private state thread When stopping the private state thread, there was a race condition between the time the thread exits (resetting the HostThread object) and the time a Join was attempted, especially in the case of a timeout. The previous workaround of copying the HostThread object is not enough, since on a Reset the internal thread stuff gets nulled out regardless of which HostThread object actually has Reset called on it, resulting in an attempt to dereference a null pointer on the subsequent call to Join from the copy as well. Additionally, there was a race between the detach (called when stopping the process) and the stop itself, causing the stop to time out because it was waiting for the private state thread to see the stop state, but it had exited immediately after entering the detached state. Patch by cameron314 Differential Revision: http://reviews.llvm.org/D19122 llvm-svn: 266733 --- lldb/include/lldb/Target/Process.h | 5 ++++- lldb/source/Target/Process.cpp | 12 ++++-------- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/lldb/include/lldb/Target/Process.h b/lldb/include/lldb/Target/Process.h index fd483f0..8feca35 100644 --- a/lldb/include/lldb/Target/Process.h +++ b/lldb/include/lldb/Target/Process.h @@ -3310,7 +3310,10 @@ protected: bool PrivateStateThreadIsValid () const { - return m_private_state_thread.IsJoinable(); + lldb::StateType state = m_private_state.GetValue(); + return state != lldb::eStateDetached && + state != lldb::eStateExited && + m_private_state_thread.IsJoinable(); } void diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp index 6a9328f..d15d1416 100644 --- a/lldb/source/Target/Process.cpp +++ b/lldb/source/Target/Process.cpp @@ -4112,11 +4112,8 @@ Process::ControlPrivateStateThread (uint32_t signal) if (log) log->Printf ("Process::%s (signal = %d)", __FUNCTION__, signal); - // Signal the private state thread. First we should copy this is case the - // thread starts exiting since the private state thread will NULL this out - // when it exits - HostThread private_state_thread(m_private_state_thread); - if (private_state_thread.IsJoinable()) + // Signal the private state thread + if (PrivateStateThreadIsValid()) { TimeValue timeout_time; bool timed_out; @@ -4134,7 +4131,7 @@ Process::ControlPrivateStateThread (uint32_t signal) { if (timed_out) { - Error error = private_state_thread.Cancel(); + Error error = m_private_state_thread.Cancel(); if (log) log->Printf ("Timed out responding to the control event, cancel got error: \"%s\".", error.AsCString()); } @@ -4145,7 +4142,7 @@ Process::ControlPrivateStateThread (uint32_t signal) } thread_result_t result = NULL; - private_state_thread.Join(&result); + m_private_state_thread.Join(&result); m_private_state_thread.Reset(); } } @@ -4449,7 +4446,6 @@ Process::RunPrivateStateThread (bool is_secondary_thread) if (!is_secondary_thread) m_public_run_lock.SetStopped(); m_private_state_control_wait.SetValue (true, eBroadcastAlways); - m_private_state_thread.Reset(); return NULL; } -- 2.7.4