11#include "llvm/ADT/StringExtras.h"
21using namespace std::chrono;
40 llvm::StringRef payload, std::chrono::seconds interrupt_timeout,
46 std::lock_guard<std::mutex> lock(
m_mutex);
59 std::chrono::seconds computed_timeout = std::min(interrupt_timeout,
66 switch (read_result) {
68 std::lock_guard<std::mutex> lock(
m_mutex);
72 auto cur_time = steady_clock::now();
82 std::chrono::duration_cast<std::chrono::seconds>(new_wait));
90 LLDB_LOGF(log,
"GDBRemoteClientBase::%s () ReadPacket(...) => false",
97 const char stop_type = response.
GetChar();
98 LLDB_LOGF(log,
"GDBRemoteClientBase::%s () got packet: %s", __FUNCTION__,
109 LLDB_LOGF(log,
"GDBRemoteClientBase::%s () unrecognized async packet",
113 std::string inferior_stdout;
128 const bool should_stop =
ShouldStop(signals, response);
146 switch (cont_lock.
lock()) {
161 int signo, std::chrono::seconds interrupt_timeout) {
162 Lock lock(*
this, interrupt_timeout);
173 Lock lock(*
this, interrupt_timeout);
183 std::chrono::seconds interrupt_timeout,
bool sync_on_timeout) {
184 Lock lock(*
this, interrupt_timeout);
188 "GDBRemoteClientBase::%s failed to get mutex, not sending "
190 __FUNCTION__,
int(payload.size()), payload.data());
200 bool sync_on_timeout,
201 llvm::function_ref<
void(llvm::StringRef)> output_callback) {
202 auto result =
ReadPacket(response, timeout, sync_on_timeout);
208 output_callback(output);
209 result =
ReadPacket(response, timeout, sync_on_timeout);
217 std::chrono::seconds interrupt_timeout,
218 llvm::function_ref<
void(llvm::StringRef)> output_callback) {
219 Lock lock(*
this, interrupt_timeout);
223 "GDBRemoteClientBase::%s failed to get mutex, not sending "
225 __FUNCTION__,
int(payload.size()), payload.data());
231 return packet_result;
240 bool sync_on_timeout) {
243 return packet_result;
245 const size_t max_response_retries = 3;
246 for (
size_t i = 0; i < max_response_retries; ++i) {
250 return packet_result;
253 return packet_result;
258 "error: packet with payload \"%.*s\" got invalid response \"%s\": %s",
259 int(payload.size()), payload.data(), response.
GetStringRef().data(),
260 (i == (max_response_retries - 1))
261 ?
"using invalid response and giving up"
262 :
"ignoring response and waiting for another");
264 return packet_result;
269 std::lock_guard<std::mutex> lock(
m_mutex);
280 ReadPacket(extra_stop_reply_packet, milliseconds(100),
false);
284 const uint8_t signo = response.
GetHexU8(UINT8_MAX);
320 std::unique_lock<std::mutex>
lock(
m_comm.m_mutex);
321 m_comm.m_is_running =
false;
330 LLDB_LOGF(log,
"GDBRemoteClientBase::ContinueLock::%s() resuming with %s",
331 __FUNCTION__,
m_comm.m_continue_packet.c_str());
334 std::unique_lock<std::mutex>
lock(
m_comm.m_mutex);
336 if (
m_comm.m_should_stop) {
337 m_comm.m_should_stop =
false;
338 LLDB_LOGF(log,
"GDBRemoteClientBase::ContinueLock::%s() cancelled",
342 if (
m_comm.SendPacketNoLock(
m_comm.m_continue_packet) !=
347 m_comm.m_is_running =
true;
357 std::chrono::seconds interrupt_timeout)
368 std::unique_lock<std::mutex> lock(
m_comm.m_mutex);
374 if (
m_comm.m_is_running) {
375 if (
m_comm.m_async_count == 1) {
378 const char ctrl_c =
'\x03';
380 size_t bytes_written =
m_comm.Write(&ctrl_c, 1, status,
nullptr);
381 if (bytes_written == 0) {
383 LLDB_LOGF(log,
"GDBRemoteClientBase::Lock::Lock failed to send "
389 log->
PutCString(
"GDBRemoteClientBase::Lock::Lock sent packet: \\x03");
391 m_comm.m_cv.wait(lock, [
this] {
return !
m_comm.m_is_running; });
401 std::unique_lock<std::mutex> lock(
m_comm.m_mutex);
static const seconds kWakeupInterval(5)
#define LLDB_LOGF(log,...)
Broadcaster(lldb::BroadcasterManagerSP manager_sp, std::string name)
Construct with a broadcaster with a name.
void BroadcastEvent(lldb::EventSP &event_sp)
Broadcast an event which has no associated data.
void PutCString(const char *cstr)
int32_t GetSignalNumberFromName(const char *name) const
GDBRemoteClientBase & m_comm
ContinueLock(GDBRemoteClientBase &comm)
Lock(GDBRemoteClientBase &comm, std::chrono::seconds interrupt_timeout=std::chrono::seconds(0))
GDBRemoteClientBase & m_comm
bool DidInterrupt() const
void SyncWithContinueThread()
std::unique_lock< std::recursive_mutex > m_async_lock
std::chrono::seconds m_interrupt_timeout
std::recursive_mutex m_async_mutex
This handles the synchronization between individual async threads.
bool SendAsyncSignal(int signo, std::chrono::seconds interrupt_timeout)
std::string m_continue_packet
Packet with which to resume after an async interrupt.
@ eBroadcastBitRunPacketSent
GDBRemoteClientBase(const char *comm_name)
uint32_t m_async_count
Number of threads interested in sending.
bool Interrupt(std::chrono::seconds interrupt_timeout)
PacketResult SendPacketAndReceiveResponseWithOutputSupport(llvm::StringRef payload, StringExtractorGDBRemote &response, std::chrono::seconds interrupt_timeout, llvm::function_ref< void(llvm::StringRef)> output_callback)
bool ShouldStop(const UnixSignals &signals, StringExtractorGDBRemote &response)
PacketResult SendPacketAndWaitForResponse(llvm::StringRef payload, StringExtractorGDBRemote &response, std::chrono::seconds interrupt_timeout=std::chrono::seconds(0), bool sync_on_timeout=true)
std::mutex m_mutex
Variables handling synchronization between the Continue thread and any other threads wishing to send ...
std::chrono::time_point< std::chrono::steady_clock > m_interrupt_endpoint
When was the interrupt packet sent.
bool m_is_running
Whether the continue thread has control.
PacketResult ReadPacketWithOutputSupport(StringExtractorGDBRemote &response, Timeout< std::micro > timeout, bool sync_on_timeout, llvm::function_ref< void(llvm::StringRef)> output_callback)
bool m_should_stop
Whether we should resume after a stop.
PacketResult SendPacketAndWaitForResponseNoLock(llvm::StringRef payload, StringExtractorGDBRemote &response, bool sync_on_timeout=true)
lldb::StateType SendContinuePacketAndWaitForResponse(ContinueDelegate &delegate, const UnixSignals &signals, llvm::StringRef payload, std::chrono::seconds interrupt_timeout, StringExtractorGDBRemote &response)
virtual void OnRunPacketSent(bool first)
PacketResult ReadPacket(StringExtractorGDBRemote &response, Timeout< std::micro > timeout, bool sync_on_timeout)
PacketResult SendPacketNoLock(llvm::StringRef payload)
std::chrono::seconds GetPacketTimeout() const
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.
@ eConnectionStatusSuccess
Success.
StateType
Process and Thread States.
@ eStateStopped
Process or thread is stopped and can be examined.
@ eStateExited
Process has exited and can't be examined.
virtual ~ContinueDelegate()
virtual void HandleStopReply()=0
virtual void HandleAsyncMisc(llvm::StringRef data)=0
virtual void HandleAsyncStructuredDataPacket(llvm::StringRef data)=0
Process asynchronously-received structured data.
virtual void HandleAsyncStdout(llvm::StringRef out)=0