[Lldb-commits] [lldb] e5e61fc - [lldb][Windows] Surface DebugBreakProcess Halt() as a SIGSTOP signal stop (#201885)
via lldb-commits
lldb-commits at lists.llvm.org
Wed Jun 10 06:04:35 PDT 2026
Author: Charles Zablit
Date: 2026-06-10T14:04:30+01:00
New Revision: e5e61fc32f6a9dd4fa75d932e9a7177a1b2bec28
URL: https://github.com/llvm/llvm-project/commit/e5e61fc32f6a9dd4fa75d932e9a7177a1b2bec28
DIFF: https://github.com/llvm/llvm-project/commit/e5e61fc32f6a9dd4fa75d932e9a7177a1b2bec28.diff
LOG: [lldb][Windows] Surface DebugBreakProcess Halt() as a SIGSTOP signal stop (#201885)
With #201884, each keystroke arriving while the debuggee is running
triggers a `\x03` BREAK. On Windows, the halt is implemented by
injecting a thread that fires an int3. However, the resulting breakpoint
exception was being reported as a real `__debugbreak()` (SIGTRAP). The
client treats that as a genuine stop, ends the continue, and stdin
forwarding ships at most one byte per BP hit.
With this patch, when a halt is pending, the server treats the next
breakpoint as the halt acknowledgement and report it as SIGSTOP instead
of SIGTRAP. The client then resumes the debuggee automatically, making
the brief halt transparent.
This is a follow up to https://github.com/llvm/llvm-project/pull/201884.
rdar://178725947
---------
Co-authored-by: Nerixyz <nero.9 at hotmail.de>
Added:
Modified:
lldb/source/Plugins/Process/Windows/Common/NativeProcessWindows.cpp
lldb/source/Plugins/Process/Windows/Common/NativeProcessWindows.h
Removed:
################################################################################
diff --git a/lldb/source/Plugins/Process/Windows/Common/NativeProcessWindows.cpp b/lldb/source/Plugins/Process/Windows/Common/NativeProcessWindows.cpp
index bf447c9ea81f5..1cdc7918d7859 100644
--- a/lldb/source/Plugins/Process/Windows/Common/NativeProcessWindows.cpp
+++ b/lldb/source/Plugins/Process/Windows/Common/NativeProcessWindows.cpp
@@ -173,8 +173,13 @@ NativeProcessWindows::GetThreadByID(lldb::tid_t thread_id) {
Status NativeProcessWindows::Halt() {
bool caused_stop = false;
StateType state = GetState();
- if (state != eStateStopped)
- return HaltProcess(caused_stop);
+ if (state != eStateStopped) {
+ m_pending_halt = true;
+ Status err = HaltProcess(caused_stop);
+ if (err.Fail() || !caused_stop)
+ m_pending_halt = false;
+ return err;
+ }
return Status();
}
@@ -581,6 +586,32 @@ NativeProcessWindows::HandleBreakpointException(const ExceptionRecord &record) {
// Any remaining STATUS_BREAKPOINT is a breakpoint instruction in the
// program's own code (e.g. `__debugbreak()` or `__builtin_debugtrap()`).
// Stop the debugger and let the user decide what to do.
+ if (m_pending_halt) {
+ LLDB_LOG(log,
+ "DebugBreakProcess injection treated as Halt SIGSTOP for tid "
+ "{0:x}",
+ thread_id);
+ m_pending_halt = false;
+ ThreadStopInfo signal_info;
+ signal_info.reason = StopReason::eStopReasonSignal;
+ signal_info.signo = 19; // SIGSTOP on POSIX
+
+ // Halt all threads at the kernel level.
+ for (uint32_t i = 0; i < m_threads.size(); ++i) {
+ auto t = static_cast<NativeThreadWindows *>(m_threads[i].get());
+ if (Status err = t->DoStop(); err.Fail()) {
+ LLDB_LOG(log, "Failed to stop thread {1:x}: {0}", t->GetID(),
+ err.GetError());
+ exit(1);
+ }
+ }
+ SetCurrentThreadID(thread_id);
+ if (NativeThreadWindows *injected = GetThreadByID(thread_id))
+ injected->SetStopReason(signal_info, "interrupt");
+ SetState(eStateStopped, true);
+ return ExceptionResult::BreakInDebugger;
+ }
+
std::string desc = formatv("Exception {0:x8} encountered at address {1:x8}",
record.GetExceptionCode(), exception_addr)
.str();
diff --git a/lldb/source/Plugins/Process/Windows/Common/NativeProcessWindows.h b/lldb/source/Plugins/Process/Windows/Common/NativeProcessWindows.h
index cac3920d82aa9..d1c57fc01e06b 100644
--- a/lldb/source/Plugins/Process/Windows/Common/NativeProcessWindows.h
+++ b/lldb/source/Plugins/Process/Windows/Common/NativeProcessWindows.h
@@ -167,6 +167,9 @@ class NativeProcessWindows : public NativeProcessProtocol,
/// launch / attach.
bool m_initial_stop_seen = false;
+ /// Set when Halt() / Interrupt() schedules a DebugBreakProcess injection.
+ bool m_pending_halt = false;
+
/// PseudoConsole for the lldb-server stdio-forwarding path.
std::shared_ptr<PseudoConsole> m_pty;
More information about the lldb-commits
mailing list