11
11
#include " llvm/ADT/StringExtras.h"
12
12
13
13
#include " lldb/Target/UnixSignals.h"
14
+ #include " lldb/Utility/Connection.h"
14
15
#include " lldb/Utility/LLDBAssert.h"
15
16
16
17
#include " ProcessGDBRemoteLog.h"
@@ -52,13 +53,15 @@ StateType GDBRemoteClientBase::SendContinuePacketAndWaitForResponse(
52
53
if (!cont_lock)
53
54
return eStateInvalid;
54
55
OnRunPacketSent (true );
55
- // The main ReadPacket loop wakes up at computed_timeout intervals, just to
56
+ // The main ReadPacket loop wakes up at computed_timeout intervals, just to
56
57
// check that the connection hasn't dropped. When we wake up we also check
57
58
// 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
+ // If we want a shorter interrupt timeout that kWakeupInterval, we need to
59
60
// choose the shorter interval for the wake up as well.
60
- std::chrono::seconds computed_timeout = std::min (interrupt_timeout,
61
- kWakeupInterval );
61
+ std::chrono::seconds computed_timeout =
62
+ std::min (interrupt_timeout, kWakeupInterval );
63
+ std::chrono::time_point<std::chrono::steady_clock> interrupt_endpoint;
64
+ bool interrupt_sent = false ;
62
65
for (;;) {
63
66
PacketResult read_result = ReadPacket (response, computed_timeout, false );
64
67
// Reset the computed_timeout to the default value in case we are going
@@ -70,16 +73,35 @@ StateType GDBRemoteClientBase::SendContinuePacketAndWaitForResponse(
70
73
if (m_async_count == 0 ) {
71
74
continue ;
72
75
}
76
+ if (!interrupt_sent) {
77
+ const char ctrl_c = ' \x03 ' ;
78
+ ConnectionStatus status = eConnectionStatusSuccess;
79
+ size_t bytes_written = Write (&ctrl_c, 1 , status, nullptr );
80
+ if (bytes_written == 0 ) {
81
+ LLDB_LOG (log, " failed to send interrupt packet" );
82
+ return eStateInvalid;
83
+ }
84
+ interrupt_endpoint = steady_clock::now () + interrupt_timeout;
85
+ if (log)
86
+ log->PutCString (
87
+ " GDBRemoteClientBase::SendContinuePacketAndWaitForResponse sent "
88
+ " packet: \\ x03" );
89
+
90
+ interrupt_sent = true ;
91
+ continue ;
92
+ }
93
+
73
94
auto cur_time = steady_clock::now ();
74
- if (cur_time >= m_interrupt_endpoint )
95
+ if (cur_time >= interrupt_endpoint )
75
96
return eStateInvalid;
76
97
else {
77
98
// We woke up and found an interrupt is in flight, but we haven't
78
99
// exceeded the interrupt wait time. So reset the wait time to the
79
100
// time left till the interrupt timeout. But don't wait longer
80
101
// than our wakeup timeout.
81
- auto new_wait = m_interrupt_endpoint - cur_time;
82
- computed_timeout = std::min (kWakeupInterval ,
102
+ auto new_wait = interrupt_endpoint - cur_time;
103
+ computed_timeout = std::min (
104
+ kWakeupInterval ,
83
105
std::chrono::duration_cast<std::chrono::seconds>(new_wait));
84
106
continue ;
85
107
}
@@ -347,30 +369,18 @@ GDBRemoteClientBase::Lock::Lock(GDBRemoteClientBase &comm,
347
369
}
348
370
349
371
void GDBRemoteClientBase::Lock::SyncWithContinueThread () {
350
- Log *log = GetLog (GDBRLog::Process|GDBRLog::Packets);
351
372
std::unique_lock<std::mutex> lock (m_comm.m_mutex );
352
373
if (m_comm.m_is_running && m_interrupt_timeout == std::chrono::seconds (0 ))
353
374
return ; // We were asked to avoid interrupting the sender. Lock is not
354
375
// acquired.
355
376
356
377
++m_comm.m_async_count ;
357
378
if (m_comm.m_is_running ) {
358
- if (m_comm.m_async_count == 1 ) {
359
- // The sender has sent the continue packet and we are the first async
360
- // packet. Let's interrupt it.
361
- const char ctrl_c = ' \x03 ' ;
362
- ConnectionStatus status = eConnectionStatusSuccess;
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 "
367
- " interrupt packet" );
368
- return ;
369
- }
370
- m_comm.m_interrupt_endpoint = steady_clock::now () + m_interrupt_timeout;
371
- if (log)
372
- log->PutCString (" GDBRemoteClientBase::Lock::Lock sent packet: \\ x03" );
373
- }
379
+ // SendContinuePacketAndWaitForResponse() takes care of sending
380
+ // the actual interrupt packet since we've increased m_async_count.
381
+ // Interrupt the ReadPacket() call to avoid having to wait for
382
+ // the interrupt timeout.
383
+ m_comm.GetConnection ()->InterruptRead ();
374
384
m_comm.m_cv .wait (lock, [this ] { return !m_comm.m_is_running ; });
375
385
m_did_interrupt = true ;
376
386
}
0 commit comments