Make processes use InputReaders for their input. Move the process

ReadThread stuff into the main Process class (out of the Process Plugins).
This has the (intended) side effect of disabling the command line tool
from reading input/commands while the process is running (the input is
directed to the running process rather than to the command interpreter).

llvm-svn: 119329
This commit is contained in:
Caroline Tice 2010-11-16 05:07:41 +00:00
parent 7d19efd6ff
commit ef5c6d02f5
6 changed files with 182 additions and 54 deletions

View File

@ -20,6 +20,7 @@
#include "lldb/Interpreter/Args.h"
#include "lldb/Interpreter/Options.h"
#include "lldb/Core/Broadcaster.h"
#include "lldb/Core/Communication.h"
#include "lldb/Core/Error.h"
#include "lldb/Core/Event.h"
#include "lldb/Core/StringList.h"
@ -1678,6 +1679,10 @@ protected:
UnixSignals m_unix_signals; /// This is the current signal set for this process.
ConstString m_target_triple;
lldb::ABISP m_abi_sp;
lldb::InputReaderSP m_process_input_reader;
lldb_private::Communication m_stdio_communication;
lldb_private::Mutex m_stdio_comm_mutex;
std::string m_stdout_data;
typedef std::map<lldb::LanguageType, lldb::LanguageRuntimeSP> LanguageRuntimeCollection;
LanguageRuntimeCollection m_language_runtimes;
@ -1739,6 +1744,32 @@ protected:
size_t
WriteMemoryPrivate (lldb::addr_t addr, const void *buf, size_t size, Error &error);
void
AppendSTDOUT (const char *s, size_t len);
static void
STDIOReadThreadBytesReceived (void *baton, const void *src, size_t src_len);
void
PushProcessInputReader ();
void
PopProcessInputReader ();
void
ResetProcessInputReader ();
void
SetUpProcessInputReader (int file_descriptor);
static size_t
ProcessInputReaderCallback (void *baton,
InputReader &reader,
lldb::InputReaderAction notification,
const char *bytes,
size_t bytes_len);
private:
//------------------------------------------------------------------
// For Process only

View File

@ -38,6 +38,7 @@ using namespace lldb_private;
ConnectionFileDescriptor::ConnectionFileDescriptor () :
Connection(),
m_fd (-1),
m_is_socket (false),
m_should_close_fd (false)
{
lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION | LIBLLDB_LOG_OBJECT,
@ -48,6 +49,7 @@ ConnectionFileDescriptor::ConnectionFileDescriptor () :
ConnectionFileDescriptor::ConnectionFileDescriptor (int fd, bool owns_fd) :
Connection(),
m_fd (fd),
m_is_socket (false),
m_should_close_fd (owns_fd)
{
lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION | LIBLLDB_LOG_OBJECT,

View File

@ -324,22 +324,8 @@ Debugger::DispatchInputCallback (void *baton, const void *bytes, size_t bytes_le
void
Debugger::DispatchInput (const char *bytes, size_t bytes_len)
{
if (bytes == NULL || bytes_len == 0)
return;
// TODO: implement the STDIO to the process as an input reader...
TargetSP target = GetSelectedTarget();
if (target.get() != NULL)
{
ProcessSP process_sp = target->GetProcessSP();
if (process_sp.get() != NULL
&& StateIsRunningState (process_sp->GetState()))
{
Error error;
if (process_sp->PutSTDIN (bytes, bytes_len, error) == bytes_len)
return;
}
}
// if (bytes == NULL || bytes_len == 0)
// return;
WriteToDefaultReader (bytes, bytes_len);
}

View File

@ -104,9 +104,7 @@ ProcessGDBRemote::ProcessGDBRemote(Target& target, Listener &listener) :
Process (target, listener),
m_dynamic_loader_ap (),
m_flags (0),
m_stdio_communication ("gdb-remote.stdio"),
m_stdio_mutex (Mutex::eMutexTypeRecursive),
m_stdout_data (),
m_byte_order (eByteOrderHost),
m_gdb_comm(),
m_debugserver_pid (LLDB_INVALID_PROCESS_ID),
@ -1634,23 +1632,23 @@ ProcessGDBRemote::DoSignal (int signo)
return error;
}
void
ProcessGDBRemote::STDIOReadThreadBytesReceived (void *baton, const void *src, size_t src_len)
{
ProcessGDBRemote *process = (ProcessGDBRemote *)baton;
process->AppendSTDOUT(static_cast<const char *>(src), src_len);
}
//void
//ProcessGDBRemote::STDIOReadThreadBytesReceived (void *baton, const void *src, size_t src_len)
//{
// ProcessGDBRemote *process = (ProcessGDBRemote *)baton;
// process->AppendSTDOUT(static_cast<const char *>(src), src_len);
//}
void
ProcessGDBRemote::AppendSTDOUT (const char* s, size_t len)
{
ProcessGDBRemoteLog::LogIf (GDBR_LOG_PROCESS, "ProcessGDBRemote::%s (<%d> %s) ...", __FUNCTION__, len, s);
Mutex::Locker locker(m_stdio_mutex);
m_stdout_data.append(s, len);
// FIXME: Make a real data object for this and put it out.
BroadcastEventIfUnique (eBroadcastBitSTDOUT);
}
//void
//ProcessGDBRemote::AppendSTDOUT (const char* s, size_t len)
//{
// ProcessGDBRemoteLog::LogIf (GDBR_LOG_PROCESS, "ProcessGDBRemote::%s (<%d> %s) ...", __FUNCTION__, len, s);
// Mutex::Locker locker(m_stdio_mutex);
// m_stdout_data.append(s, len);
//
// // FIXME: Make a real data object for this and put it out.
// BroadcastEventIfUnique (eBroadcastBitSTDOUT);
//}
Error
@ -1867,18 +1865,7 @@ ProcessGDBRemote::StartDebugserverProcess
if (m_debugserver_pid != LLDB_INVALID_PROCESS_ID)
{
if (pty.GetMasterFileDescriptor() != lldb_utility::PseudoTerminal::invalid_fd)
{
std::auto_ptr<ConnectionFileDescriptor> conn_ap(new ConnectionFileDescriptor (pty.ReleaseMasterFileDescriptor(), true));
if (conn_ap.get())
{
m_stdio_communication.SetConnection(conn_ap.release());
if (m_stdio_communication.IsConnected())
{
m_stdio_communication.SetReadThreadBytesReceivedCallback (STDIOReadThreadBytesReceived, this);
m_stdio_communication.StartReadThread();
}
}
}
SetUpProcessInputReader (pty.ReleaseMasterFileDescriptor());
}
}
else

View File

@ -261,11 +261,11 @@ protected:
bool
ProcessIDIsValid ( ) const;
static void
STDIOReadThreadBytesReceived (void *baton, const void *src, size_t src_len);
// static void
// STDIOReadThreadBytesReceived (void *baton, const void *src, size_t src_len);
void
AppendSTDOUT (const char* s, size_t len);
// void
// AppendSTDOUT (const char* s, size_t len);
void
Clear ( );
@ -321,9 +321,7 @@ protected:
std::auto_ptr<lldb_private::DynamicLoader> m_dynamic_loader_ap;
lldb_private::Flags m_flags; // Process specific flags (see eFlags enums)
lldb_private::Communication m_stdio_communication;
lldb_private::Mutex m_stdio_mutex; // Multithreaded protection for stdio
std::string m_stdout_data;
lldb::ByteOrder m_byte_order;
GDBRemoteCommunication m_gdb_comm;
lldb::pid_t m_debugserver_pid;

View File

@ -14,7 +14,9 @@
#include "lldb/Breakpoint/StoppointCallbackContext.h"
#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Core/Event.h"
#include "lldb/Core/ConnectionFileDescriptor.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/InputReader.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/State.h"
@ -85,7 +87,11 @@ Process::Process(Target &target, Listener &listener) :
m_notifications (),
m_persistent_vars(),
m_listener(listener),
m_unix_signals ()
m_unix_signals (),
m_process_input_reader (),
m_stdio_communication ("lldb.process.stdio"),
m_stdio_comm_mutex (Mutex::eMutexTypeRecursive),
m_stdout_data ()
{
UpdateInstanceName();
@ -1160,6 +1166,7 @@ Process::Launch
Error error;
m_target_triple.Clear();
m_abi_sp.reset();
m_process_input_reader.reset();
Module *exe_module = m_target.GetExecutableModule().get();
if (exe_module)
@ -1305,6 +1312,7 @@ Process::Attach (lldb::pid_t attach_pid)
m_target_triple.Clear();
m_abi_sp.reset();
m_process_input_reader.reset();
// Find the process and its architecture. Make sure it matches the architecture
// of the current Target, and if not adjust it.
@ -1347,6 +1355,7 @@ Process::Attach (const char *process_name, bool wait_for_launch)
{
m_target_triple.Clear();
m_abi_sp.reset();
m_process_input_reader.reset();
// Find the process and its architecture. Make sure it matches the architecture
// of the current Target, and if not adjust it.
@ -1467,6 +1476,12 @@ Process::Destroy ()
DidDestroy();
StopPrivateStateThread();
}
m_stdio_communication.StopReadThread();
m_stdio_communication.Disconnect();
if (m_process_input_reader && m_process_input_reader->IsActive())
m_target.GetDebugger().PopInputReader (m_process_input_reader);
if (m_process_input_reader)
m_process_input_reader.reset();
}
return error;
}
@ -1714,6 +1729,10 @@ Process::HandlePrivateEvent (EventSP &event_sp)
{
log->Printf ("\tChanging public state from: %s to %s", StateAsCString(GetState ()), StateAsCString (internal_state));
}
if (StateIsRunningState (internal_state))
PushProcessInputReader ();
else
PopProcessInputReader ();
Process::ProcessEventData::SetUpdateStateOnRemoval(event_sp.get());
BroadcastEvent (event_sp);
}
@ -2035,6 +2054,111 @@ Process::GetArchSpecForExistingProcess (const char *process_name)
return Host::GetArchSpecForExistingProcess (process_name);
}
void
Process::AppendSTDOUT (const char * s, size_t len)
{
Mutex::Locker locker (m_stdio_comm_mutex);
m_stdout_data.append (s, len);
BroadcastEventIfUnique (eBroadcastBitSTDOUT);
}
void
Process::STDIOReadThreadBytesReceived (void *baton, const void *src, size_t src_len)
{
Process *process = (Process *) baton;
process->AppendSTDOUT (static_cast<const char *>(src), src_len);
}
size_t
Process::ProcessInputReaderCallback (void *baton,
InputReader &reader,
lldb::InputReaderAction notification,
const char *bytes,
size_t bytes_len)
{
Process *process = (Process *) baton;
switch (notification)
{
case eInputReaderActivate:
break;
case eInputReaderDeactivate:
break;
case eInputReaderReactivate:
break;
case eInputReaderGotToken:
{
Error error;
process->PutSTDIN (bytes, bytes_len, error);
}
break;
case eInputReaderDone:
break;
}
return bytes_len;
}
void
Process::ResetProcessInputReader ()
{
m_process_input_reader.reset();
}
void
Process::SetUpProcessInputReader (int file_descriptor)
{
// First set up the Read Thread for reading/handling process I/O
std::auto_ptr<ConnectionFileDescriptor> conn_ap (new ConnectionFileDescriptor (file_descriptor, true));
if (conn_ap.get())
{
m_stdio_communication.SetConnection (conn_ap.release());
if (m_stdio_communication.IsConnected())
{
m_stdio_communication.SetReadThreadBytesReceivedCallback (STDIOReadThreadBytesReceived, this);
m_stdio_communication.StartReadThread();
// Now read thread is set up, set up input reader.
if (!m_process_input_reader.get())
{
m_process_input_reader.reset (new InputReader(m_target.GetDebugger()));
Error err (m_process_input_reader->Initialize (Process::ProcessInputReaderCallback,
this,
eInputReaderGranularityByte,
NULL,
NULL,
false));
if (err.Fail())
m_process_input_reader.reset();
}
}
}
}
void
Process::PushProcessInputReader ()
{
if (m_process_input_reader && !m_process_input_reader->IsActive())
m_target.GetDebugger().PushInputReader (m_process_input_reader);
}
void
Process::PopProcessInputReader ()
{
if (m_process_input_reader && m_process_input_reader->IsActive())
m_target.GetDebugger().PopInputReader (m_process_input_reader);
}
lldb::UserSettingsControllerSP
Process::GetSettingsController (bool finish)
{