forked from OSchip/llvm-project
[lldb] [llgs] Fix disabling non-stop mode
Stop all processes and clear notification queues when disabling non-stop mode. Ensure that no stop notifications are sent for processes stopped due to the mode switch. Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.llvm.org/D128893
This commit is contained in:
parent
5d6659739c
commit
c732afa2c2
|
@ -1919,6 +1919,20 @@ GDBRemoteCommunicationServerLLGS::SendStopReasonForState(
|
|||
bool force_synchronous) {
|
||||
Log *log = GetLog(LLDBLog::Process);
|
||||
|
||||
if (m_disabling_non_stop) {
|
||||
// Check if we are waiting for any more processes to stop. If we are,
|
||||
// do not send the OK response yet.
|
||||
for (const auto &it : m_debugged_processes) {
|
||||
if (it.second.process_up->IsRunning())
|
||||
return PacketResult::Success;
|
||||
}
|
||||
|
||||
// If all expected processes were stopped after a QNonStop:0 request,
|
||||
// send the OK response.
|
||||
m_disabling_non_stop = false;
|
||||
return SendOKResponse();
|
||||
}
|
||||
|
||||
switch (process_state) {
|
||||
case eStateAttaching:
|
||||
case eStateLaunching:
|
||||
|
@ -3903,12 +3917,33 @@ GDBRemoteCommunicationServerLLGS::Handle_qSaveCore(
|
|||
GDBRemoteCommunication::PacketResult
|
||||
GDBRemoteCommunicationServerLLGS::Handle_QNonStop(
|
||||
StringExtractorGDBRemote &packet) {
|
||||
Log *log = GetLog(LLDBLog::Process);
|
||||
|
||||
StringRef packet_str{packet.GetStringRef()};
|
||||
assert(packet_str.startswith("QNonStop:"));
|
||||
packet_str.consume_front("QNonStop:");
|
||||
if (packet_str == "0") {
|
||||
for (auto &process_it : m_debugged_processes) {
|
||||
if (process_it.second.process_up->IsRunning()) {
|
||||
assert(m_non_stop);
|
||||
Status error = process_it.second.process_up->Interrupt();
|
||||
if (error.Fail()) {
|
||||
LLDB_LOG(log,
|
||||
"while disabling nonstop, failed to halt process {0}: {1}",
|
||||
process_it.first, error);
|
||||
return SendErrorResponse(0x41);
|
||||
}
|
||||
// we must not send stop reasons after QNonStop
|
||||
m_disabling_non_stop = true;
|
||||
}
|
||||
}
|
||||
m_stdio_notification_queue.clear();
|
||||
m_stop_notification_queue.clear();
|
||||
m_non_stop = false;
|
||||
// TODO: stop all threads
|
||||
// If we are stopping anything, defer sending the OK response until we're
|
||||
// done.
|
||||
if (m_disabling_non_stop)
|
||||
return PacketResult::Success;
|
||||
} else if (packet_str == "1") {
|
||||
m_non_stop = true;
|
||||
} else
|
||||
|
|
|
@ -117,6 +117,7 @@ protected:
|
|||
bool m_thread_suffix_supported = false;
|
||||
bool m_list_threads_in_stop_reply = false;
|
||||
bool m_non_stop = false;
|
||||
bool m_disabling_non_stop = false;
|
||||
std::deque<std::string> m_stdio_notification_queue;
|
||||
std::deque<std::string> m_stop_notification_queue;
|
||||
|
||||
|
|
|
@ -362,3 +362,33 @@ class LldbGdbServerTestCase(gdbremote_testcase.GdbRemoteTestCaseBase):
|
|||
"send packet: $OK#00",
|
||||
], True)
|
||||
self.expect_gdbremote_sequence()
|
||||
|
||||
@add_test_categories(["llgs"])
|
||||
def test_leave_nonstop(self):
|
||||
self.build()
|
||||
self.set_inferior_startup_launch()
|
||||
procs = self.prep_debug_monitor_and_inferior(
|
||||
inferior_args=["thread:new", "thread:new", "stop", "sleep:15"])
|
||||
self.test_sequence.add_log_lines(
|
||||
["read packet: $QNonStop:1#00",
|
||||
"send packet: $OK#00",
|
||||
# stop is used to synchronize starting threads
|
||||
"read packet: $c#63",
|
||||
"send packet: $OK#00",
|
||||
{"direction": "send", "regex": "%Stop:T.*"},
|
||||
"read packet: $c#63",
|
||||
"send packet: $OK#00",
|
||||
# verify that the threads are running now
|
||||
"read packet: $?#00",
|
||||
"send packet: $OK#00",
|
||||
"read packet: $QNonStop:0#00",
|
||||
"send packet: $OK#00",
|
||||
# we should issue some random request now to verify that the stub
|
||||
# did not send stop reasons -- we may verify whether notification
|
||||
# queue was cleared while at it
|
||||
"read packet: $vStopped#00",
|
||||
"send packet: $Eff#00",
|
||||
"read packet: $?#00",
|
||||
{"direction": "send", "regex": "[$]T.*"},
|
||||
], True)
|
||||
self.expect_gdbremote_sequence()
|
||||
|
|
Loading…
Reference in New Issue