11 #include "llvm/ADT/StringExtras.h"
21 using namespace std::chrono;
32 GDBRemoteClientBase::ContinueDelegate::~ContinueDelegate() =
default;
34 GDBRemoteClientBase::GDBRemoteClientBase(
const char *comm_name,
35 const char *listener_name)
37 m_is_running(false), m_should_stop(false) {}
41 llvm::StringRef payload, std::chrono::seconds interrupt_timeout,
47 std::lock_guard<std::mutex> lock(
m_mutex);
60 std::chrono::seconds computed_timeout = std::min(interrupt_timeout,
67 switch (read_result) {
69 std::lock_guard<std::mutex> lock(
m_mutex);
73 auto cur_time = steady_clock::now();
83 std::chrono::duration_cast<std::chrono::seconds>(new_wait));
91 LLDB_LOGF(log,
"GDBRemoteClientBase::%s () ReadPacket(...) => false",
98 const char stop_type = response.
GetChar();
99 LLDB_LOGF(log,
"GDBRemoteClientBase::%s () got packet: %s", __FUNCTION__,
110 LLDB_LOGF(log,
"GDBRemoteClientBase::%s () unrecognized async packet",
129 const bool should_stop =
ShouldStop(signals, response);
147 switch (cont_lock.
lock()) {
162 int signo, std::chrono::seconds interrupt_timeout) {
163 Lock lock(*
this, interrupt_timeout);
174 Lock lock(*
this, interrupt_timeout);
184 std::chrono::seconds interrupt_timeout) {
185 Lock lock(*
this, interrupt_timeout);
189 "GDBRemoteClientBase::%s failed to get mutex, not sending "
191 __FUNCTION__,
int(payload.size()), payload.data());
201 std::chrono::seconds interrupt_timeout,
202 llvm::function_ref<
void(llvm::StringRef)> output_callback) {
203 Lock lock(*
this, interrupt_timeout);
207 "GDBRemoteClientBase::%s failed to get mutex, not sending "
209 __FUNCTION__,
int(payload.size()), payload.data());
215 return packet_result;
226 return packet_result;
228 const size_t max_response_retries = 3;
229 for (
size_t i = 0; i < max_response_retries; ++i) {
233 return packet_result;
236 return packet_result;
241 "error: packet with payload \"%.*s\" got invalid response \"%s\": %s",
242 int(payload.size()), payload.data(), response.
GetStringRef().data(),
243 (i == (max_response_retries - 1))
244 ?
"using invalid response and giving up"
245 :
"ignoring response and waiting for another");
247 return packet_result;
252 std::lock_guard<std::mutex> lock(
m_mutex);
263 ReadPacket(extra_stop_reply_packet, milliseconds(100),
false);
267 const uint8_t signo = response.
GetHexU8(UINT8_MAX);
291 : m_comm(comm), m_acquired(false) {
303 std::unique_lock<std::mutex> lock(m_comm.m_mutex);
304 m_comm.m_is_running =
false;
306 m_comm.m_cv.notify_all();
313 LLDB_LOGF(log,
"GDBRemoteClientBase::ContinueLock::%s() resuming with %s",
314 __FUNCTION__, m_comm.m_continue_packet.c_str());
317 std::unique_lock<std::mutex> lock(m_comm.m_mutex);
318 m_comm.m_cv.wait(lock, [
this] {
return m_comm.m_async_count == 0; });
319 if (m_comm.m_should_stop) {
320 m_comm.m_should_stop =
false;
321 LLDB_LOGF(log,
"GDBRemoteClientBase::ContinueLock::%s() cancelled",
323 return LockResult::Cancelled;
325 if (m_comm.SendPacketNoLock(m_comm.m_continue_packet) !=
327 return LockResult::Failed;
330 m_comm.m_is_running =
true;
332 return LockResult::Success;
340 std::chrono::seconds interrupt_timeout)
341 : m_async_lock(comm.
m_async_mutex, std::defer_lock), m_comm(comm),
342 m_interrupt_timeout(interrupt_timeout), m_acquired(false),
343 m_did_interrupt(false) {
351 std::unique_lock<std::mutex> lock(m_comm.m_mutex);
352 if (m_comm.m_is_running && m_interrupt_timeout == std::chrono::seconds(0))
356 ++m_comm.m_async_count;
357 if (m_comm.m_is_running) {
358 if (m_comm.m_async_count == 1) {
361 const char ctrl_c =
'\x03';
363 size_t bytes_written = m_comm.Write(&ctrl_c, 1, status,
nullptr);
364 if (bytes_written == 0) {
365 --m_comm.m_async_count;
366 LLDB_LOGF(log,
"GDBRemoteClientBase::Lock::Lock failed to send "
370 m_comm.m_interrupt_endpoint = steady_clock::now() + m_interrupt_timeout;
372 log->
PutCString(
"GDBRemoteClientBase::Lock::Lock sent packet: \\x03");
374 m_comm.m_cv.wait(lock, [
this] {
return !m_comm.m_is_running; });
375 m_did_interrupt =
true;
384 std::unique_lock<std::mutex> lock(m_comm.m_mutex);
385 --m_comm.m_async_count;
387 m_comm.m_cv.notify_one();