20#include "llvm/Support/Compiler.h"
26#include <shared_mutex>
36 static constexpr llvm::StringLiteral class_name(
"lldb.communication");
42 m_read_thread_did_exit(false), m_bytes(), m_bytes_mutex(),
43 m_synchronize_mutex(), m_callback(nullptr), m_callback_baton(nullptr) {
45 "{0} ThreadedCommunication::ThreadedCommunication (name = {1})",
49 SetEventName(eBroadcastBitReadThreadGotBytes,
"got bytes");
50 SetEventName(eBroadcastBitReadThreadDidExit,
"read thread did exit");
51 SetEventName(eBroadcastBitReadThreadShouldExit,
"read thread should exit");
52 SetEventName(eBroadcastBitPacketAvailable,
"packet available");
53 SetEventName(eBroadcastBitNoMorePendingInput,
"no more pending input");
60 "{0} ThreadedCommunication::~ThreadedCommunication (name = {1})",
72 "Disconnecting while the read thread is running is racy!");
83 "this = {0}, dst = {1}, dst_len = {2}, timeout = {3}, connection = {4}",
89 if (cached_bytes > 0) {
93 if (timeout && timeout->count() == 0) {
110 listener_sp->StartListeningForEvents(
111 this, eBroadcastBitReadThreadGotBytes | eBroadcastBitReadThreadDidExit);
116 if (cached_bytes > 0) {
125 event_sp = std::make_shared<Event>(eBroadcastBitReadThreadDidExit);
127 if (!listener_sp->GetEvent(event_sp, timeout)) {
134 const uint32_t event_type = event_sp->GetType();
135 if (event_type & eBroadcastBitReadThreadGotBytes) {
139 if (event_type & eBroadcastBitReadThreadDidExit) {
150 llvm_unreachable(
"Got unexpected event type!");
168 "{0} ThreadedCommunication::StartReadThread ()",
this);
170 const std::string thread_name =
176 thread_name, [
this] {
return ReadThread(); });
184 "failed to launch host thread: {0}");
201 "{0} ThreadedCommunication::StopReadThread ()",
this);
208 return error.Success();
218 return error.Success();
229 const size_t len = std::min<size_t>(dst_len,
m_bytes.size());
231 ::memcpy(dst,
m_bytes.c_str(), len);
243 "{0} ThreadedCommunication::AppendBytesToCache (src = {1}, src_len "
246 this, bytes, (uint64_t)len, broadcast);
247 if ((bytes ==
nullptr || len == 0) &&
253 }
else if (bytes !=
nullptr && len > 0) {
255 m_bytes.append((
const char *)bytes, len);
268 LLDB_LOG(log,
"Communication({0}) thread starting...",
this);
275 bool disconnect =
false;
278 buf,
sizeof(buf), std::chrono::seconds(5), status, &
error);
320 LLDB_LOG(log,
"Communication({0}) thread exiting...",
this);
357 "ThreadedCommunication::SyncronizeWithReadThread"));
358 listener_sp->StartListeningForEvents(
this, eBroadcastBitNoMorePendingInput);
369 listener_sp->GetEvent(event_sp, std::nullopt);
373 std::unique_ptr<Connection> connection) {
static llvm::raw_ostream & error(Stream &strm)
#define LLDB_LOG(log,...)
The LLDB_LOG* macros defined below are the way to emit log messages.
#define LLDB_LOG_ERROR(log, error,...)
static void ReadThreadBytesReceived(void *baton, const void *src, size_t src_len)
An event broadcasting class.
void SetEventName(uint32_t event_mask, const char *name)
Set the name for an event bit.
const std::string & GetBroadcasterName()
Get this broadcaster's name.
void BroadcastEventIfUnique(lldb::EventSP &event_sp)
void BroadcastEvent(lldb::EventSP &event_sp)
Broadcast an event which has no associated data.
void CheckInWithManager()
An abstract communications class.
size_t ReadFromConnection(void *dst, size_t dst_len, const Timeout< std::micro > &timeout, lldb::ConnectionStatus &status, Status *error_ptr)
bool GetCloseOnEOF() const
virtual size_t Read(void *dst, size_t dst_len, const Timeout< std::micro > &timeout, lldb::ConnectionStatus &status, Status *error_ptr)
Read bytes from the current connection.
lldb::ConnectionSP m_connection_sp
The connection that is current in use by this communications class.
virtual void SetConnection(std::unique_ptr< Connection > connection)
Sets the connection that it to be used by this class.
virtual lldb::ConnectionStatus Disconnect(Status *error_ptr=nullptr)
Disconnect the communications connection if one is currently connected.
static std::string ConnectionStatusAsString(lldb::ConnectionStatus status)
Status Join(lldb::thread_result_t *result)
static lldb::ListenerSP MakeListener(const char *name)
void Clear()
Clear the object state.
static Status FromErrorString(const char *str)
static Status FromError(llvm::Error error)
Avoid using this in new code. Migrate APIs to llvm::Expected instead.
static llvm::Expected< HostThread > LaunchThread(llvm::StringRef name, std::function< lldb::thread_result_t()> thread_function, size_t min_stack_byte_size=0)
virtual void AppendBytesToCache(const uint8_t *src, size_t src_len, bool broadcast, lldb::ConnectionStatus status)
Append new bytes that get read from the read thread into the internal object byte cache.
size_t Read(void *dst, size_t dst_len, const Timeout< std::micro > &timeout, lldb::ConnectionStatus &status, Status *error_ptr) override
Read bytes from the current connection.
void SetConnection(std::unique_ptr< Connection > connection) override
Sets the connection that it to be used by this class.
ThreadedCommunication(const char *broadcaster_name)
Construct the ThreadedCommunication object with the specified name for the Broadcaster that this obje...
std::recursive_mutex m_bytes_mutex
A mutex to protect multi-threaded access to the cached bytes.
HostThread m_read_thread
The read thread handle in case we need to cancel the thread.
~ThreadedCommunication() override
Destructor.
virtual bool StopReadThread(Status *error_ptr=nullptr)
Stops the read thread by cancelling it.
void SynchronizeWithReadThread()
Wait for the read thread to process all outstanding data.
std::atomic< bool > m_read_thread_did_exit
Whether the read thread is enabled.
lldb::ConnectionStatus m_pass_status
Connection status passthrough from read thread.
lldb::ConnectionStatus Disconnect(Status *error_ptr=nullptr) override
Disconnect the communications connection if one is currently connected.
std::mutex m_read_thread_mutex
ReadThreadBytesReceived m_callback
Status m_pass_error
Error passthrough from read thread.
virtual bool StartReadThread(Status *error_ptr=nullptr)
Starts a read thread whose sole purpose it to read bytes from the current connection.
std::atomic< bool > m_read_thread_enabled
Whether the read thread is enabled.
static llvm::StringRef GetStaticBroadcasterClass()
virtual bool JoinReadThread(Status *error_ptr=nullptr)
std::string m_bytes
A buffer to cache bytes read in the ReadThread function.
size_t GetCachedBytes(void *dst, size_t dst_len)
Get any available bytes from our data cache.
bool ReadThreadIsRunning()
Checks if there is a currently running read thread.
lldb::thread_result_t ReadThread()
The read thread function.
std::mutex m_synchronize_mutex
void SetReadThreadBytesReceivedCallback(ReadThreadBytesReceived callback, void *callback_baton)
A class that represents a running process on the host machine.
Log * GetLog(Cat mask)
Retrieve the Log object for the channel associated with the given log enum.
ConnectionStatus
Connection Status Types.
@ eConnectionStatusError
Check GetError() for details.
@ eConnectionStatusInterrupted
Interrupted read.
@ eConnectionStatusTimedOut
Request timed out.
@ eConnectionStatusEndOfFile
End-of-file encountered.
@ eConnectionStatusSuccess
Success.
@ eConnectionStatusLostConnection
Lost connection while connected to a valid connection.
@ eConnectionStatusNoConnection
No connection.
@ eErrorTypePOSIX
POSIX error codes.
std::shared_ptr< lldb_private::Event > EventSP
std::shared_ptr< lldb_private::Listener > ListenerSP