@@ -20,7 +20,10 @@ using namespace lldb_private;
20
20
using namespace lldb_private ::process_gdb_remote;
21
21
using namespace std ::chrono;
22
22
23
- static const seconds kInterruptTimeout (5 );
23
+ // When we've sent a continue packet and are waiting for the target to stop,
24
+ // we wake up the wait with this interval to make sure the stub hasn't gone
25
+ // away while we were waiting.
26
+ static const seconds kWakeupInterval (5 );
24
27
25
28
// ///////////////////////
26
29
// GDBRemoteClientBase //
@@ -35,7 +38,8 @@ GDBRemoteClientBase::GDBRemoteClientBase(const char *comm_name,
35
38
36
39
StateType GDBRemoteClientBase::SendContinuePacketAndWaitForResponse (
37
40
ContinueDelegate &delegate, const UnixSignals &signals,
38
- llvm::StringRef payload, StringExtractorGDBRemote &response) {
41
+ llvm::StringRef payload, std::chrono::seconds interrupt_timeout,
42
+ StringExtractorGDBRemote &response) {
39
43
Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
40
44
response.Clear ();
41
45
@@ -48,16 +52,34 @@ StateType GDBRemoteClientBase::SendContinuePacketAndWaitForResponse(
48
52
if (!cont_lock)
49
53
return eStateInvalid;
50
54
OnRunPacketSent (true );
51
-
55
+ // The main ReadPacket loop wakes up at computed_timeout intervals, just to
56
+ // check that the connection hasn't dropped. When we wake up we also check
57
+ // whether there is an interrupt request that has reached its endpoint.
58
+ // If we want a shorter interrupt timeout that kWakeupInterval, we need to
59
+ // choose the shorter interval for the wake up as well.
60
+ std::chrono::seconds computed_timeout = std::min (interrupt_timeout,
61
+ kWakeupInterval );
52
62
for (;;) {
53
- PacketResult read_result = ReadPacket (response, kInterruptTimeout , false );
63
+ PacketResult read_result = ReadPacket (response, computed_timeout , false );
54
64
switch (read_result) {
55
65
case PacketResult::ErrorReplyTimeout: {
56
66
std::lock_guard<std::mutex> lock (m_mutex);
57
- if (m_async_count == 0 )
67
+ if (m_async_count == 0 ) {
58
68
continue ;
59
- if (steady_clock::now () >= m_interrupt_time + kInterruptTimeout )
69
+ }
70
+ auto cur_time = steady_clock::now ();
71
+ if (cur_time >= m_interrupt_endpoint)
60
72
return eStateInvalid;
73
+ else {
74
+ // We woke up and found an interrupt is in flight, but we haven't
75
+ // exceeded the interrupt wait time. So reset the wait time to the
76
+ // time left till the interrupt timeout. But don't wait longer
77
+ // than our wakeup timeout.
78
+ auto new_wait = m_interrupt_endpoint - cur_time;
79
+ computed_timeout = std::min (kWakeupInterval ,
80
+ std::chrono::duration_cast<std::chrono::seconds>(new_wait));
81
+ continue ;
82
+ }
61
83
break ;
62
84
}
63
85
case PacketResult::Success:
@@ -133,8 +155,9 @@ StateType GDBRemoteClientBase::SendContinuePacketAndWaitForResponse(
133
155
}
134
156
}
135
157
136
- bool GDBRemoteClientBase::SendAsyncSignal (int signo) {
137
- Lock lock (*this , true );
158
+ bool GDBRemoteClientBase::SendAsyncSignal (
159
+ int signo, std::chrono::seconds interrupt_timeout) {
160
+ Lock lock (*this , interrupt_timeout);
138
161
if (!lock || !lock.DidInterrupt ())
139
162
return false ;
140
163
@@ -144,25 +167,26 @@ bool GDBRemoteClientBase::SendAsyncSignal(int signo) {
144
167
return true ;
145
168
}
146
169
147
- bool GDBRemoteClientBase::Interrupt () {
148
- Lock lock (*this , true );
170
+ bool GDBRemoteClientBase::Interrupt (std::chrono::seconds interrupt_timeout ) {
171
+ Lock lock (*this , interrupt_timeout );
149
172
if (!lock.DidInterrupt ())
150
173
return false ;
151
174
m_should_stop = true ;
152
175
return true ;
153
176
}
177
+
154
178
GDBRemoteCommunication::PacketResult
155
179
GDBRemoteClientBase::SendPacketAndWaitForResponse (
156
180
llvm::StringRef payload, StringExtractorGDBRemote &response,
157
- bool send_async ) {
158
- Lock lock (*this , send_async );
181
+ std::chrono::seconds interrupt_timeout ) {
182
+ Lock lock (*this , interrupt_timeout );
159
183
if (!lock) {
160
184
if (Log *log =
161
185
ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS))
162
186
LLDB_LOGF (log,
163
187
" GDBRemoteClientBase::%s failed to get mutex, not sending "
164
- " packet '%.*s' (send_async=%d) " ,
165
- __FUNCTION__, int (payload.size ()), payload.data (), send_async );
188
+ " packet '%.*s'" ,
189
+ __FUNCTION__, int (payload.size ()), payload.data ());
166
190
return PacketResult::ErrorSendFailed;
167
191
}
168
192
@@ -172,16 +196,16 @@ GDBRemoteClientBase::SendPacketAndWaitForResponse(
172
196
GDBRemoteCommunication::PacketResult
173
197
GDBRemoteClientBase::SendPacketAndReceiveResponseWithOutputSupport (
174
198
llvm::StringRef payload, StringExtractorGDBRemote &response,
175
- bool send_async ,
199
+ std::chrono::seconds interrupt_timeout ,
176
200
llvm::function_ref<void (llvm::StringRef)> output_callback) {
177
- Lock lock (*this , send_async );
201
+ Lock lock (*this , interrupt_timeout );
178
202
if (!lock) {
179
203
if (Log *log =
180
204
ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS))
181
205
LLDB_LOGF (log,
182
206
" GDBRemoteClientBase::%s failed to get mutex, not sending "
183
- " packet '%.*s' (send_async=%d) " ,
184
- __FUNCTION__, int (payload.size ()), payload.data (), send_async );
207
+ " packet '%.*s'" ,
208
+ __FUNCTION__, int (payload.size ()), payload.data ());
185
209
return PacketResult::ErrorSendFailed;
186
210
}
187
211
@@ -222,13 +246,14 @@ GDBRemoteClientBase::SendPacketAndWaitForResponseNoLock(
222
246
return packet_result;
223
247
}
224
248
225
- bool GDBRemoteClientBase::SendvContPacket (llvm::StringRef payload,
226
- StringExtractorGDBRemote &response) {
249
+ bool GDBRemoteClientBase::SendvContPacket (
250
+ llvm::StringRef payload, std::chrono::seconds interrupt_timeout,
251
+ StringExtractorGDBRemote &response) {
227
252
Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
228
253
LLDB_LOGF (log, " GDBRemoteCommunicationClient::%s ()" , __FUNCTION__);
229
254
230
255
// we want to lock down packet sending while we continue
231
- Lock lock (*this , true );
256
+ Lock lock (*this , interrupt_timeout );
232
257
233
258
LLDB_LOGF (log,
234
259
" GDBRemoteCommunicationClient::%s () sending vCont packet: %.*s" ,
@@ -336,18 +361,20 @@ GDBRemoteClientBase::ContinueLock::lock() {
336
361
// GDBRemoteClientBase::Lock //
337
362
// /////////////////////////////
338
363
339
- GDBRemoteClientBase::Lock::Lock (GDBRemoteClientBase &comm, bool interrupt)
364
+ GDBRemoteClientBase::Lock::Lock (GDBRemoteClientBase &comm,
365
+ std::chrono::seconds interrupt_timeout)
340
366
: m_async_lock(comm.m_async_mutex, std::defer_lock), m_comm(comm),
341
- m_acquired(false ), m_did_interrupt(false ) {
342
- SyncWithContinueThread (interrupt);
367
+ m_interrupt_timeout(interrupt_timeout), m_acquired(false ),
368
+ m_did_interrupt(false ) {
369
+ SyncWithContinueThread ();
343
370
if (m_acquired)
344
371
m_async_lock.lock ();
345
372
}
346
373
347
- void GDBRemoteClientBase::Lock::SyncWithContinueThread (bool interrupt ) {
374
+ void GDBRemoteClientBase::Lock::SyncWithContinueThread () {
348
375
Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
349
376
std::unique_lock<std::mutex> lock (m_comm.m_mutex );
350
- if (m_comm.m_is_running && !interrupt )
377
+ if (m_comm.m_is_running && m_interrupt_timeout == std::chrono::seconds ( 0 ) )
351
378
return ; // We were asked to avoid interrupting the sender. Lock is not
352
379
// acquired.
353
380
@@ -365,9 +392,9 @@ void GDBRemoteClientBase::Lock::SyncWithContinueThread(bool interrupt) {
365
392
" interrupt packet" );
366
393
return ;
367
394
}
395
+ m_comm.m_interrupt_endpoint = steady_clock::now () + m_interrupt_timeout;
368
396
if (log)
369
397
log->PutCString (" GDBRemoteClientBase::Lock::Lock sent packet: \\ x03" );
370
- m_comm.m_interrupt_time = steady_clock::now ();
371
398
}
372
399
m_comm.m_cv .wait (lock, [this ] { return !m_comm.m_is_running ; });
373
400
m_did_interrupt = true ;
0 commit comments