forked from OSchip/llvm-project
Adding support for setting thread stop state when a process stops.
This re-submission of this patch fixes a problem where the code sometimes caused a deadlock. The Process::SetPrivateState method was locking the Process::m_private_state variable and then later calling ThreadList::DidStop, which locks the ThreadList mutex. Other methods in ThreadList which were being called from other threads lock the ThreadList mutex and then call Process::GetPrivateState which locks the Process::m_private_state mutex. To avoid deadlocks, Process::SetPrivateState now locks the ThreadList mutex before locking the Process::m_private_state mutex. llvm-svn: 181609
This commit is contained in:
parent
72a196a159
commit
29d65744c9
|
@ -277,6 +277,10 @@ public:
|
|||
virtual void
|
||||
DidResume ();
|
||||
|
||||
// This notifies the thread when a private stop occurs.
|
||||
virtual void
|
||||
DidStop ();
|
||||
|
||||
virtual void
|
||||
RefreshStateAfterStop() = 0;
|
||||
|
||||
|
|
|
@ -119,6 +119,9 @@ public:
|
|||
void
|
||||
DidResume ();
|
||||
|
||||
void
|
||||
DidStop ();
|
||||
|
||||
void
|
||||
DiscardThreadPlans();
|
||||
|
||||
|
|
|
@ -1699,6 +1699,7 @@ Process::SetPrivateState (StateType new_state)
|
|||
if (log)
|
||||
log->Printf("Process::SetPrivateState (%s)", StateAsCString(new_state));
|
||||
|
||||
Mutex::Locker thread_locker(m_thread_list.GetMutex());
|
||||
Mutex::Locker locker(m_private_state.GetMutex());
|
||||
|
||||
const StateType old_state = m_private_state.GetValueNoLock ();
|
||||
|
@ -1722,6 +1723,19 @@ Process::SetPrivateState (StateType new_state)
|
|||
m_private_state.SetValueNoLock (new_state);
|
||||
if (StateIsStoppedState(new_state, false))
|
||||
{
|
||||
// Note, this currently assumes that all threads in the list
|
||||
// stop when the process stops. In the future we will want to
|
||||
// support a debugging model where some threads continue to run
|
||||
// while others are stopped. When that happens we will either need
|
||||
// a way for the thread list to identify which threads are stopping
|
||||
// or create a special thread list containing only threads which
|
||||
// actually stopped.
|
||||
//
|
||||
// The process plugin is responsible for managing the actual
|
||||
// behavior of the threads and should have stopped any threads
|
||||
// that are going to stop before we get here.
|
||||
m_thread_list.DidStop();
|
||||
|
||||
m_mod_id.BumpStopID();
|
||||
m_memory_cache.Clear();
|
||||
if (log)
|
||||
|
|
|
@ -658,6 +658,12 @@ Thread::DidResume ()
|
|||
SetResumeSignal (LLDB_INVALID_SIGNAL_NUMBER);
|
||||
}
|
||||
|
||||
void
|
||||
Thread::DidStop ()
|
||||
{
|
||||
SetState (eStateStopped);
|
||||
}
|
||||
|
||||
bool
|
||||
Thread::ShouldStop (Event* event_ptr)
|
||||
{
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include <algorithm>
|
||||
|
||||
#include "lldb/Core/Log.h"
|
||||
#include "lldb/Core/State.h"
|
||||
#include "lldb/Target/RegisterContext.h"
|
||||
#include "lldb/Target/ThreadList.h"
|
||||
#include "lldb/Target/Thread.h"
|
||||
|
@ -643,6 +644,27 @@ ThreadList::DidResume ()
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
ThreadList::DidStop ()
|
||||
{
|
||||
Mutex::Locker locker(GetMutex());
|
||||
collection::iterator pos, end = m_threads.end();
|
||||
for (pos = m_threads.begin(); pos != end; ++pos)
|
||||
{
|
||||
// Notify threads that the process just stopped.
|
||||
// Note, this currently assumes that all threads in the list
|
||||
// stop when the process stops. In the future we will want to support
|
||||
// a debugging model where some threads continue to run while others
|
||||
// are stopped. We either need to handle that somehow here or
|
||||
// create a special thread list containing only threads which will
|
||||
// stop in the code that calls this method (currently
|
||||
// Process::SetPrivateState).
|
||||
ThreadSP thread_sp(*pos);
|
||||
if (StateIsRunningState(thread_sp->GetState()))
|
||||
thread_sp->DidStop ();
|
||||
}
|
||||
}
|
||||
|
||||
ThreadSP
|
||||
ThreadList::GetSelectedThread ()
|
||||
{
|
||||
|
|
|
@ -14,14 +14,12 @@ class StopThreadsTestCase(TestBase):
|
|||
|
||||
@unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
|
||||
@dsym_test
|
||||
@unittest2.expectedFailure("PR-15824") # thread states not properly maintained
|
||||
def test_state_after_breakpoint_with_dsym(self):
|
||||
"""Test thread state after breakpoint."""
|
||||
self.buildDsym()
|
||||
self.thread_state_after_breakpoint_test()
|
||||
|
||||
@dwarf_test
|
||||
@unittest2.expectedFailure("PR-15824") # thread states not properly maintained
|
||||
def test_state_after_breakpoint_with_dwarf(self):
|
||||
"""Test thread state after breakpoint."""
|
||||
self.buildDwarf()
|
||||
|
|
Loading…
Reference in New Issue