From ef5c6d02f54ee66cbe467e7de6fc38a274ebe943 Mon Sep 17 00:00:00 2001 From: Caroline Tice Date: Tue, 16 Nov 2010 05:07:41 +0000 Subject: [PATCH] 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 --- lldb/include/lldb/Target/Process.h | 33 ++++- lldb/source/Core/ConnectionFileDescriptor.cpp | 2 + lldb/source/Core/Debugger.cpp | 18 +-- .../Process/gdb-remote/ProcessGDBRemote.cpp | 47 +++---- .../Process/gdb-remote/ProcessGDBRemote.h | 10 +- lldb/source/Target/Process.cpp | 126 +++++++++++++++++- 6 files changed, 182 insertions(+), 54 deletions(-) diff --git a/lldb/include/lldb/Target/Process.h b/lldb/include/lldb/Target/Process.h index 82a87aa4947c..f8684abcf6da 100644 --- a/lldb/include/lldb/Target/Process.h +++ b/lldb/include/lldb/Target/Process.h @@ -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 LanguageRuntimeCollection; LanguageRuntimeCollection m_language_runtimes; @@ -1738,7 +1743,33 @@ 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 diff --git a/lldb/source/Core/ConnectionFileDescriptor.cpp b/lldb/source/Core/ConnectionFileDescriptor.cpp index 8029ad3b6432..96d70bc10125 100644 --- a/lldb/source/Core/ConnectionFileDescriptor.cpp +++ b/lldb/source/Core/ConnectionFileDescriptor.cpp @@ -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, diff --git a/lldb/source/Core/Debugger.cpp b/lldb/source/Core/Debugger.cpp index 625969b28471..5e6f93c91d45 100644 --- a/lldb/source/Core/Debugger.cpp +++ b/lldb/source/Core/Debugger.cpp @@ -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); } diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp index 93c673029816..52499ba173ae 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp @@ -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(src), src_len); -} +//void +//ProcessGDBRemote::STDIOReadThreadBytesReceived (void *baton, const void *src, size_t src_len) +//{ +// ProcessGDBRemote *process = (ProcessGDBRemote *)baton; +// process->AppendSTDOUT(static_cast(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 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 diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h index 6330c7b0fb2c..ae79c5a48bc9 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h +++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h @@ -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 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; diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp index c9b5579be5d3..ea6b200f3184 100644 --- a/lldb/source/Target/Process.cpp +++ b/lldb/source/Target/Process.cpp @@ -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(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 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) {