aboutsummaryrefslogtreecommitdiff
path: root/lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.cpp')
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.cpp84
1 files changed, 57 insertions, 27 deletions
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.cpp
index fdaa60e2df41..a4c71e864a76 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.cpp
@@ -20,7 +20,10 @@ using namespace lldb_private;
using namespace lldb_private::process_gdb_remote;
using namespace std::chrono;
-static const seconds kInterruptTimeout(5);
+// When we've sent a continue packet and are waiting for the target to stop,
+// we wake up the wait with this interval to make sure the stub hasn't gone
+// away while we were waiting.
+static const seconds kWakeupInterval(5);
/////////////////////////
// GDBRemoteClientBase //
@@ -35,7 +38,8 @@ GDBRemoteClientBase::GDBRemoteClientBase(const char *comm_name,
StateType GDBRemoteClientBase::SendContinuePacketAndWaitForResponse(
ContinueDelegate &delegate, const UnixSignals &signals,
- llvm::StringRef payload, StringExtractorGDBRemote &response) {
+ llvm::StringRef payload, std::chrono::seconds interrupt_timeout,
+ StringExtractorGDBRemote &response) {
Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
response.Clear();
@@ -48,16 +52,37 @@ StateType GDBRemoteClientBase::SendContinuePacketAndWaitForResponse(
if (!cont_lock)
return eStateInvalid;
OnRunPacketSent(true);
-
+ // The main ReadPacket loop wakes up at computed_timeout intervals, just to
+ // check that the connection hasn't dropped. When we wake up we also check
+ // whether there is an interrupt request that has reached its endpoint.
+ // If we want a shorter interrupt timeout that kWakeupInterval, we need to
+ // choose the shorter interval for the wake up as well.
+ std::chrono::seconds computed_timeout = std::min(interrupt_timeout,
+ kWakeupInterval);
for (;;) {
- PacketResult read_result = ReadPacket(response, kInterruptTimeout, false);
+ PacketResult read_result = ReadPacket(response, computed_timeout, false);
+ // Reset the computed_timeout to the default value in case we are going
+ // round again.
+ computed_timeout = std::min(interrupt_timeout, kWakeupInterval);
switch (read_result) {
case PacketResult::ErrorReplyTimeout: {
std::lock_guard<std::mutex> lock(m_mutex);
- if (m_async_count == 0)
+ if (m_async_count == 0) {
continue;
- if (steady_clock::now() >= m_interrupt_time + kInterruptTimeout)
+ }
+ auto cur_time = steady_clock::now();
+ if (cur_time >= m_interrupt_endpoint)
return eStateInvalid;
+ else {
+ // We woke up and found an interrupt is in flight, but we haven't
+ // exceeded the interrupt wait time. So reset the wait time to the
+ // time left till the interrupt timeout. But don't wait longer
+ // than our wakeup timeout.
+ auto new_wait = m_interrupt_endpoint - cur_time;
+ computed_timeout = std::min(kWakeupInterval,
+ std::chrono::duration_cast<std::chrono::seconds>(new_wait));
+ continue;
+ }
break;
}
case PacketResult::Success:
@@ -133,8 +158,9 @@ StateType GDBRemoteClientBase::SendContinuePacketAndWaitForResponse(
}
}
-bool GDBRemoteClientBase::SendAsyncSignal(int signo) {
- Lock lock(*this, true);
+bool GDBRemoteClientBase::SendAsyncSignal(
+ int signo, std::chrono::seconds interrupt_timeout) {
+ Lock lock(*this, interrupt_timeout);
if (!lock || !lock.DidInterrupt())
return false;
@@ -144,25 +170,26 @@ bool GDBRemoteClientBase::SendAsyncSignal(int signo) {
return true;
}
-bool GDBRemoteClientBase::Interrupt() {
- Lock lock(*this, true);
+bool GDBRemoteClientBase::Interrupt(std::chrono::seconds interrupt_timeout) {
+ Lock lock(*this, interrupt_timeout);
if (!lock.DidInterrupt())
return false;
m_should_stop = true;
return true;
}
+
GDBRemoteCommunication::PacketResult
GDBRemoteClientBase::SendPacketAndWaitForResponse(
llvm::StringRef payload, StringExtractorGDBRemote &response,
- bool send_async) {
- Lock lock(*this, send_async);
+ std::chrono::seconds interrupt_timeout) {
+ Lock lock(*this, interrupt_timeout);
if (!lock) {
if (Log *log =
ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS))
LLDB_LOGF(log,
"GDBRemoteClientBase::%s failed to get mutex, not sending "
- "packet '%.*s' (send_async=%d)",
- __FUNCTION__, int(payload.size()), payload.data(), send_async);
+ "packet '%.*s'",
+ __FUNCTION__, int(payload.size()), payload.data());
return PacketResult::ErrorSendFailed;
}
@@ -172,16 +199,16 @@ GDBRemoteClientBase::SendPacketAndWaitForResponse(
GDBRemoteCommunication::PacketResult
GDBRemoteClientBase::SendPacketAndReceiveResponseWithOutputSupport(
llvm::StringRef payload, StringExtractorGDBRemote &response,
- bool send_async,
+ std::chrono::seconds interrupt_timeout,
llvm::function_ref<void(llvm::StringRef)> output_callback) {
- Lock lock(*this, send_async);
+ Lock lock(*this, interrupt_timeout);
if (!lock) {
if (Log *log =
ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS))
LLDB_LOGF(log,
"GDBRemoteClientBase::%s failed to get mutex, not sending "
- "packet '%.*s' (send_async=%d)",
- __FUNCTION__, int(payload.size()), payload.data(), send_async);
+ "packet '%.*s'",
+ __FUNCTION__, int(payload.size()), payload.data());
return PacketResult::ErrorSendFailed;
}
@@ -222,13 +249,14 @@ GDBRemoteClientBase::SendPacketAndWaitForResponseNoLock(
return packet_result;
}
-bool GDBRemoteClientBase::SendvContPacket(llvm::StringRef payload,
- StringExtractorGDBRemote &response) {
+bool GDBRemoteClientBase::SendvContPacket(
+ llvm::StringRef payload, std::chrono::seconds interrupt_timeout,
+ StringExtractorGDBRemote &response) {
Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
LLDB_LOGF(log, "GDBRemoteCommunicationClient::%s ()", __FUNCTION__);
// we want to lock down packet sending while we continue
- Lock lock(*this, true);
+ Lock lock(*this, interrupt_timeout);
LLDB_LOGF(log,
"GDBRemoteCommunicationClient::%s () sending vCont packet: %.*s",
@@ -336,18 +364,20 @@ GDBRemoteClientBase::ContinueLock::lock() {
// GDBRemoteClientBase::Lock //
///////////////////////////////
-GDBRemoteClientBase::Lock::Lock(GDBRemoteClientBase &comm, bool interrupt)
+GDBRemoteClientBase::Lock::Lock(GDBRemoteClientBase &comm,
+ std::chrono::seconds interrupt_timeout)
: m_async_lock(comm.m_async_mutex, std::defer_lock), m_comm(comm),
- m_acquired(false), m_did_interrupt(false) {
- SyncWithContinueThread(interrupt);
+ m_interrupt_timeout(interrupt_timeout), m_acquired(false),
+ m_did_interrupt(false) {
+ SyncWithContinueThread();
if (m_acquired)
m_async_lock.lock();
}
-void GDBRemoteClientBase::Lock::SyncWithContinueThread(bool interrupt) {
+void GDBRemoteClientBase::Lock::SyncWithContinueThread() {
Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
std::unique_lock<std::mutex> lock(m_comm.m_mutex);
- if (m_comm.m_is_running && !interrupt)
+ if (m_comm.m_is_running && m_interrupt_timeout == std::chrono::seconds(0))
return; // We were asked to avoid interrupting the sender. Lock is not
// acquired.
@@ -365,9 +395,9 @@ void GDBRemoteClientBase::Lock::SyncWithContinueThread(bool interrupt) {
"interrupt packet");
return;
}
+ m_comm.m_interrupt_endpoint = steady_clock::now() + m_interrupt_timeout;
if (log)
log->PutCString("GDBRemoteClientBase::Lock::Lock sent packet: \\x03");
- m_comm.m_interrupt_time = steady_clock::now();
}
m_comm.m_cv.wait(lock, [this] { return !m_comm.m_is_running; });
m_did_interrupt = true;