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) {