Create new class, InputReaderStack, to better handle

mutexes around input readers and prevent deadlocking; modify
Debugger to use the new class.

llvm-svn: 132475
This commit is contained in:
Caroline Tice 2011-06-02 19:18:55 +00:00
parent 9d4a8cf481
commit d5a0a01b2d
5 changed files with 162 additions and 23 deletions

View File

@ -18,6 +18,7 @@
#include <stack>
#include "lldb/Core/Communication.h"
#include "lldb/Core/InputReaderStack.h"
#include "lldb/Core/Listener.h"
#include "lldb/Core/StreamFile.h"
#include "lldb/Core/SourceManager.h"
@ -451,8 +452,7 @@ protected:
SourceManager m_source_manager;
std::auto_ptr<CommandInterpreter> m_command_interpreter_ap;
Mutex m_input_readers_mutex;
std::stack<lldb::InputReaderSP> m_input_readers;
InputReaderStack m_input_reader_stack;
std::string m_input_reader_data;
private:

View File

@ -0,0 +1,58 @@
//===-- InputReaderStack.h --------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef liblldb_InputReaderStack_h_
#define liblldb_InputReaderStack_h_
#include <stack>
#include "lldb/lldb-private.h"
#include "lldb/Host/Mutex.h"
namespace lldb_private {
class InputReaderStack
{
public:
InputReaderStack ();
~InputReaderStack ();
size_t
GetSize () const;
void
Push (const lldb::InputReaderSP& reader_sp);
bool
IsEmpty () const;
lldb::InputReaderSP
Top ();
void
Pop ();
Mutex &
GetStackMutex ();
protected:
std::stack<lldb::InputReaderSP> m_input_readers;
mutable Mutex m_input_readers_mutex;
private:
DISALLOW_COPY_AND_ASSIGN (InputReaderStack);
};
} // namespace lldb_private
#endif // liblldb_InputReaderStack_h_

View File

@ -409,6 +409,8 @@
9A3576A8116E9AB700E8ED2F /* SBHostOS.h in Headers */ = {isa = PBXBuildFile; fileRef = 9A3576A7116E9AB700E8ED2F /* SBHostOS.h */; settings = {ATTRIBUTES = (Public, ); }; };
9A3576AA116E9AC700E8ED2F /* SBHostOS.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9A3576A9116E9AC700E8ED2F /* SBHostOS.cpp */; };
9A4F35101368A51A00823F52 /* StreamAsynchronousIO.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9A4F350F1368A51A00823F52 /* StreamAsynchronousIO.cpp */; };
9A9E1EFF1398086D005AC039 /* InputReaderStack.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9A9E1EFE1398086D005AC039 /* InputReaderStack.cpp */; };
9A9E1F0113980943005AC039 /* InputReaderStack.h in Headers */ = {isa = PBXBuildFile; fileRef = 9A9E1F0013980943005AC039 /* InputReaderStack.h */; };
9AA69DA61188F52100D753A0 /* PseudoTerminal.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2682F16A115EDA0D00CCFF99 /* PseudoTerminal.cpp */; };
9AA69DAF118A023300D753A0 /* SBInputReader.h in Headers */ = {isa = PBXBuildFile; fileRef = 9AA69DAE118A023300D753A0 /* SBInputReader.h */; settings = {ATTRIBUTES = (Public, ); }; };
9AA69DB1118A024600D753A0 /* SBInputReader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9AA69DB0118A024600D753A0 /* SBInputReader.cpp */; };
@ -1200,6 +1202,8 @@
9A9831081125FC5800A56CB0 /* SBTarget.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SBTarget.h; path = include/lldb/API/SBTarget.h; sourceTree = "<group>"; };
9A9831091125FC5800A56CB0 /* SBThread.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBThread.cpp; path = source/API/SBThread.cpp; sourceTree = "<group>"; };
9A98310A1125FC5800A56CB0 /* SBThread.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SBThread.h; path = include/lldb/API/SBThread.h; sourceTree = "<group>"; };
9A9E1EFE1398086D005AC039 /* InputReaderStack.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = InputReaderStack.cpp; path = source/Core/InputReaderStack.cpp; sourceTree = "<group>"; };
9A9E1F0013980943005AC039 /* InputReaderStack.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = InputReaderStack.h; path = include/lldb/Core/InputReaderStack.h; sourceTree = "<group>"; };
9AA69DAE118A023300D753A0 /* SBInputReader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SBInputReader.h; path = include/lldb/API/SBInputReader.h; sourceTree = "<group>"; };
9AA69DB0118A024600D753A0 /* SBInputReader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBInputReader.cpp; path = source/API/SBInputReader.cpp; sourceTree = "<group>"; };
9AA69DB5118A027A00D753A0 /* InputReader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = InputReader.cpp; path = source/Core/InputReader.cpp; sourceTree = "<group>"; };
@ -1889,6 +1893,8 @@
26BC7D6410F1B77400F91463 /* Flags.h */,
9AA69DBB118A029E00D753A0 /* InputReader.h */,
9AA69DB5118A027A00D753A0 /* InputReader.cpp */,
9A9E1F0013980943005AC039 /* InputReaderStack.h */,
9A9E1EFE1398086D005AC039 /* InputReaderStack.cpp */,
26BC7D6510F1B77400F91463 /* IOStreamMacros.h */,
26BC7D6610F1B77400F91463 /* Language.h */,
26BC7E7D10F1B85900F91463 /* Language.cpp */,
@ -2619,6 +2625,7 @@
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
9A9E1F0113980943005AC039 /* InputReaderStack.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -3201,6 +3208,7 @@
26DB3E1F1379E7AD0080DC73 /* ABISysV_x86_64.cpp in Sources */,
26A69C5F137A17A500262477 /* RegisterValue.cpp in Sources */,
2690B3711381D5C300ECFBAE /* Memory.cpp in Sources */,
9A9E1EFF1398086D005AC039 /* InputReaderStack.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};

View File

@ -230,8 +230,7 @@ Debugger::Debugger () :
m_listener ("lldb.Debugger"),
m_source_manager (),
m_command_interpreter_ap (new CommandInterpreter (*this, eScriptLanguageDefault, false)),
m_input_readers_mutex (Mutex::eMutexTypeRecursive),
m_input_readers (),
m_input_reader_stack (),
m_input_reader_data ()
{
m_command_interpreter_ap->Initialize ();
@ -357,14 +356,13 @@ Debugger::GetCurrentInputReader ()
{
InputReaderSP reader_sp;
Mutex::Locker locker (m_input_readers_mutex);
if (!m_input_readers.empty())
if (!m_input_reader_stack.IsEmpty())
{
// Clear any finished readers from the stack
while (CheckIfTopInputReaderIsDone()) ;
if (!m_input_readers.empty())
reader_sp = m_input_readers.top();
if (!m_input_reader_stack.IsEmpty())
reader_sp = m_input_reader_stack.Top();
}
return reader_sp;
@ -424,9 +422,8 @@ Debugger::CleanUpInputReaders ()
{
m_input_reader_data.clear();
Mutex::Locker locker (m_input_readers_mutex);
// The bottom input reader should be the main debugger input reader. We do not want to close that one here.
while (m_input_readers.size() > 1)
while (m_input_reader_stack.GetSize() > 1)
{
InputReaderSP reader_sp (GetCurrentInputReader ());
if (reader_sp)
@ -479,8 +476,7 @@ Debugger::WriteToDefaultReader (const char *bytes, size_t bytes_len)
if (m_input_reader_data.empty())
return;
Mutex::Locker locker (m_input_readers_mutex);
while (!m_input_readers.empty() && !m_input_reader_data.empty())
while (!m_input_reader_stack.IsEmpty() && !m_input_reader_data.empty())
{
// Get the input reader from the top of the stack
InputReaderSP reader_sp (GetCurrentInputReader ());
@ -519,8 +515,7 @@ Debugger::PushInputReader (const InputReaderSP& reader_sp)
if (top_reader_sp)
top_reader_sp->Notify (eInputReaderDeactivate);
Mutex::Locker locker (m_input_readers_mutex);
m_input_readers.push (reader_sp);
m_input_reader_stack.Push (reader_sp);
reader_sp->Notify (eInputReaderActivate);
ActivateInputReader (reader_sp);
}
@ -532,22 +527,21 @@ Debugger::PopInputReader (const lldb::InputReaderSP& pop_reader_sp)
// The reader on the stop of the stack is done, so let the next
// read on the stack referesh its prompt and if there is one...
Mutex::Locker locker (m_input_readers_mutex);
if (!m_input_readers.empty())
if (!m_input_reader_stack.IsEmpty())
{
// Cannot call GetCurrentInputReader here, as that would cause an infinite loop.
InputReaderSP reader_sp(m_input_readers.top());
InputReaderSP reader_sp(m_input_reader_stack.Top());
if (!pop_reader_sp || pop_reader_sp.get() == reader_sp.get())
{
m_input_readers.pop ();
m_input_reader_stack.Pop ();
reader_sp->Notify (eInputReaderDeactivate);
reader_sp->Notify (eInputReaderDone);
result = true;
if (!m_input_readers.empty())
if (!m_input_reader_stack.IsEmpty())
{
reader_sp = m_input_readers.top();
reader_sp = m_input_reader_stack.Top();
if (reader_sp)
{
ActivateInputReader (reader_sp);
@ -563,11 +557,10 @@ bool
Debugger::CheckIfTopInputReaderIsDone ()
{
bool result = false;
Mutex::Locker locker (m_input_readers_mutex);
if (!m_input_readers.empty())
if (!m_input_reader_stack.IsEmpty())
{
// Cannot call GetCurrentInputReader here, as that would cause an infinite loop.
InputReaderSP reader_sp(m_input_readers.top());
InputReaderSP reader_sp(m_input_reader_stack.Top());
if (reader_sp && reader_sp->IsDone())
{

View File

@ -0,0 +1,80 @@
//===-- InputReaderStack.cpp ------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "lldb/Core/InputReaderStack.h"
// C Includes
// C++ Includes
// Other libraries and framework includes
// Project includes
using namespace lldb;
using namespace lldb_private;
InputReaderStack::InputReaderStack () :
m_input_readers (),
m_input_readers_mutex (Mutex::eMutexTypeRecursive)
{
}
InputReaderStack::~InputReaderStack ()
{
}
size_t
InputReaderStack::GetSize () const
{
Mutex::Locker locker (m_input_readers_mutex);
return m_input_readers.size();
}
void
InputReaderStack::Push (const lldb::InputReaderSP& reader_sp)
{
if (reader_sp)
{
Mutex::Locker locker (m_input_readers_mutex);
m_input_readers.push (reader_sp);
}
}
bool
InputReaderStack::IsEmpty () const
{
Mutex::Locker locker (m_input_readers_mutex);
return m_input_readers.empty();
}
InputReaderSP
InputReaderStack::Top ()
{
InputReaderSP input_reader_sp;
{
Mutex::Locker locker (m_input_readers_mutex);
if (!m_input_readers.empty())
input_reader_sp = m_input_readers.top();
}
return input_reader_sp;
}
void
InputReaderStack::Pop ()
{
Mutex::Locker locker (m_input_readers_mutex);
if (!m_input_readers.empty())
m_input_readers.pop();
}
Mutex &
InputReaderStack::GetStackMutex ()
{
return m_input_readers_mutex;
}