mgorny created this revision. mgorny added reviewers: labath, krytarowski, emaste, jingham. Herald added a subscriber: arichardson. Herald added a project: All. mgorny requested review of this revision.
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 https://reviews.llvm.org/D128893 Files: lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h lldb/test/API/tools/lldb-server/TestNonStop.py Index: lldb/test/API/tools/lldb-server/TestNonStop.py =================================================================== --- lldb/test/API/tools/lldb-server/TestNonStop.py +++ lldb/test/API/tools/lldb-server/TestNonStop.py @@ -368,3 +368,33 @@ "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() Index: lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h =================================================================== --- lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h +++ lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h @@ -97,6 +97,7 @@ std::unordered_map<lldb::pid_t, std::unique_ptr<NativeProcessProtocol>> m_debugged_processes; std::unordered_set<lldb::pid_t> m_vkilled_processes; + std::unordered_set<lldb::pid_t> m_inhibit_stop_reason_processes; Communication m_stdio_communication; MainLoop::ReadHandleUP m_stdio_handle_up; Index: lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp =================================================================== --- lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp +++ lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp @@ -1910,6 +1910,12 @@ bool force_synchronous) { Log *log = GetLog(LLDBLog::Process); + auto process_it = m_inhibit_stop_reason_processes.find(process.GetID()); + if (process_it != m_inhibit_stop_reason_processes.end()) { + m_inhibit_stop_reason_processes.erase(process_it); + return PacketResult::Success; + } + switch (process_state) { case eStateAttaching: case eStateLaunching: @@ -3906,12 +3912,28 @@ 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 (const auto &process_it : m_debugged_processes) { + if (process_it.second->IsRunning()) { + Status error = process_it.second->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_inhibit_stop_reason_processes.insert(process_it.first); + } + } + m_stdio_notification_queue.clear(); + m_stop_notification_queue.clear(); m_non_stop = false; - // TODO: stop all threads } else if (packet_str == "1") { m_non_stop = true; } else
Index: lldb/test/API/tools/lldb-server/TestNonStop.py =================================================================== --- lldb/test/API/tools/lldb-server/TestNonStop.py +++ lldb/test/API/tools/lldb-server/TestNonStop.py @@ -368,3 +368,33 @@ "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() Index: lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h =================================================================== --- lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h +++ lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h @@ -97,6 +97,7 @@ std::unordered_map<lldb::pid_t, std::unique_ptr<NativeProcessProtocol>> m_debugged_processes; std::unordered_set<lldb::pid_t> m_vkilled_processes; + std::unordered_set<lldb::pid_t> m_inhibit_stop_reason_processes; Communication m_stdio_communication; MainLoop::ReadHandleUP m_stdio_handle_up; Index: lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp =================================================================== --- lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp +++ lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp @@ -1910,6 +1910,12 @@ bool force_synchronous) { Log *log = GetLog(LLDBLog::Process); + auto process_it = m_inhibit_stop_reason_processes.find(process.GetID()); + if (process_it != m_inhibit_stop_reason_processes.end()) { + m_inhibit_stop_reason_processes.erase(process_it); + return PacketResult::Success; + } + switch (process_state) { case eStateAttaching: case eStateLaunching: @@ -3906,12 +3912,28 @@ 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 (const auto &process_it : m_debugged_processes) { + if (process_it.second->IsRunning()) { + Status error = process_it.second->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_inhibit_stop_reason_processes.insert(process_it.first); + } + } + m_stdio_notification_queue.clear(); + m_stop_notification_queue.clear(); m_non_stop = false; - // TODO: stop all threads } else if (packet_str == "1") { m_non_stop = true; } else
_______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits