[Lldb-commits] [lldb] [lldb][Windows] Report a single step whose trap is still queued at a stop (PR #231502)
Charles Zablit via lldb-commits
lldb-commits at lists.llvm.org
Wed Oct 14 04:25:09 PDT 2026
https://github.com/charles-zablit updated https://github.com/llvm/llvm-project/pull/231502
>From 16ad6523c6925a2bb0a5b9640ff894058a127859 Mon Sep 17 00:00:00 2001
From: Charles Zablit <c_zablit at apple.com>
Date: Tue, 13 Oct 2026 14:15:51 +0100
Subject: [PATCH 1/2] [lldb][Windows] Report debug events queued together in
one stop
---
.../lldb/Host/common/NativeProcessProtocol.h | 5 ++-
.../Process/Windows/Common/DebuggerThread.cpp | 37 ++++++++++++++++--
.../Process/Windows/Common/DebuggerThread.h | 4 ++
.../Process/Windows/Common/IDebugDelegate.h | 3 ++
.../Windows/Common/NativeProcessWindows.cpp | 38 ++++++++++++++++---
.../Windows/Common/NativeProcessWindows.h | 17 +++++++++
6 files changed, 94 insertions(+), 10 deletions(-)
diff --git a/lldb/include/lldb/Host/common/NativeProcessProtocol.h b/lldb/include/lldb/Host/common/NativeProcessProtocol.h
index 209cb068aba215..da1fa26abefa9e 100644
--- a/lldb/include/lldb/Host/common/NativeProcessProtocol.h
+++ b/lldb/include/lldb/Host/common/NativeProcessProtocol.h
@@ -544,8 +544,11 @@ class NativeProcessProtocol {
NativeThreadProtocol *GetThreadByIDUnlocked(lldb::tid_t tid);
-private:
+ /// Notify the delegates of \p state. For plugins that set a state with
+ /// SetState(state, /*notify_delegates=*/false) and report it later.
void SynchronouslyNotifyProcessStateChanged(lldb::StateType state);
+
+private:
llvm::Expected<SoftwareBreakpoint>
EnableSoftwareBreakpoint(lldb::addr_t addr, uint32_t size_hint);
};
diff --git a/lldb/source/Plugins/Process/Windows/Common/DebuggerThread.cpp b/lldb/source/Plugins/Process/Windows/Common/DebuggerThread.cpp
index cb1e31b4334f54..6dd051e574885b 100644
--- a/lldb/source/Plugins/Process/Windows/Common/DebuggerThread.cpp
+++ b/lldb/source/Plugins/Process/Windows/Common/DebuggerThread.cpp
@@ -262,6 +262,13 @@ void DebuggerThread::ContinueAsyncException(ExceptionResult result) {
m_exception_pred.SetValue(result, eBroadcastAlways);
}
+void DebuggerThread::ReportDeferredStopAndWaitForResume() {
+ m_dll_event_pred.SetValue(false, eBroadcastNever);
+ m_debug_delegate->ReportDeferredStop();
+ if (!m_is_shutting_down)
+ m_dll_event_pred.WaitForValueEqualTo(true);
+}
+
void DebuggerThread::ContinueAsyncDllEvent() {
m_dll_event_pred.SetValue(true, eBroadcastAlways);
}
@@ -279,10 +286,28 @@ void DebuggerThread::DebugLoop() {
Log *log = GetLog(WindowsLog::Event);
DEBUG_EVENT dbe = {};
bool should_debug = true;
+ constexpr unsigned max_drained_events = 64;
+ unsigned drained_events = 0;
LLDB_LOG_VERBOSE(log, "Entering WaitForDebugEventEx loop");
while (should_debug) {
+ bool draining = !m_is_shutting_down && m_debug_delegate->HasDeferredStop();
+ if (draining && drained_events >= max_drained_events) {
+ LLDB_LOG(log, "reporting the stop after taking {0} queued debug events",
+ drained_events);
+ ReportDeferredStopAndWaitForResume();
+ draining = false;
+ }
+ if (!draining)
+ drained_events = 0;
LLDB_LOG_VERBOSE(log, "Calling WaitForDebugEvent");
- BOOL wait_result = g_wait_for_debug_event(&dbe, INFINITE);
+ BOOL wait_result = g_wait_for_debug_event(&dbe, draining ? 0 : INFINITE);
+ if (draining) {
+ if (!wait_result) {
+ ReportDeferredStopAndWaitForResume();
+ continue;
+ }
+ ++drained_events;
+ }
if (wait_result) {
DWORD continue_status = DBG_CONTINUE;
bool shutting_down = m_is_shutting_down;
@@ -447,6 +472,8 @@ DebuggerThread::HandleExceptionEvent(const EXCEPTION_DEBUG_INFO &info,
// result is what the wait below returns.
if (result != ExceptionResult::BreakInDebugger)
ContinueAsyncException(result);
+ else
+ m_debug_delegate->ReportDeferredStop();
LLDB_LOG(log, "waiting for ExceptionPred != BreakInDebugger");
result = *m_exception_pred.WaitForValueNotEqualTo(
@@ -864,8 +891,10 @@ DebuggerThread::HandleLoadDllEvent(const LOAD_DLL_DEBUG_INFO &info,
if (info.hFile != nullptr)
::CloseHandle(info.hFile);
- if (action == DllEventAction::ParkDebugLoop && !m_is_shutting_down.load())
+ if (action == DllEventAction::ParkDebugLoop && !m_is_shutting_down.load()) {
+ m_debug_delegate->ReportDeferredStop();
m_dll_event_pred.WaitForValueEqualTo(true);
+ }
return DBG_CONTINUE;
}
@@ -879,8 +908,10 @@ DebuggerThread::HandleUnloadDllEvent(const UNLOAD_DLL_DEBUG_INFO &info,
m_dll_event_pred.SetValue(false, eBroadcastNever);
DllEventAction action = m_debug_delegate->OnUnloadDll(
reinterpret_cast<lldb::addr_t>(info.lpBaseOfDll), thread_id);
- if (action == DllEventAction::ParkDebugLoop && !m_is_shutting_down.load())
+ if (action == DllEventAction::ParkDebugLoop && !m_is_shutting_down.load()) {
+ m_debug_delegate->ReportDeferredStop();
m_dll_event_pred.WaitForValueEqualTo(true);
+ }
return DBG_CONTINUE;
}
diff --git a/lldb/source/Plugins/Process/Windows/Common/DebuggerThread.h b/lldb/source/Plugins/Process/Windows/Common/DebuggerThread.h
index a9fa3ec0c7599d..cc2d3f740b77e9 100644
--- a/lldb/source/Plugins/Process/Windows/Common/DebuggerThread.h
+++ b/lldb/source/Plugins/Process/Windows/Common/DebuggerThread.h
@@ -55,6 +55,10 @@ class DebuggerThread : public std::enable_shared_from_this<DebuggerThread> {
void ContinueAsyncDllEvent();
private:
+ /// Have the delegate report the stop it collected, then wait until the
+ /// client resumes before taking the next debug event.
+ void ReportDeferredStopAndWaitForResume();
+
void FreeProcessHandles();
void DebugLoop();
ExceptionResult HandleExceptionEvent(const EXCEPTION_DEBUG_INFO &info,
diff --git a/lldb/source/Plugins/Process/Windows/Common/IDebugDelegate.h b/lldb/source/Plugins/Process/Windows/Common/IDebugDelegate.h
index cecd58a15f9c2c..f5c9b53447f3b9 100644
--- a/lldb/source/Plugins/Process/Windows/Common/IDebugDelegate.h
+++ b/lldb/source/Plugins/Process/Windows/Common/IDebugDelegate.h
@@ -37,6 +37,9 @@ class IDebugDelegate {
lldb::tid_t thread_id) = 0;
virtual DllEventAction OnUnloadDll(lldb::addr_t module_addr,
lldb::tid_t thread_id) = 0;
+ virtual bool HasDeferredStop() { return false; }
+ /// Report the stop the delegate holds, if any.
+ virtual void ReportDeferredStop() {}
virtual void OnDebugString(lldb::addr_t debug_string_addr, bool is_unicode,
uint16_t length_lower_word) = 0;
virtual void OnDebuggerError(const Status &error, uint32_t type) = 0;
diff --git a/lldb/source/Plugins/Process/Windows/Common/NativeProcessWindows.cpp b/lldb/source/Plugins/Process/Windows/Common/NativeProcessWindows.cpp
index 9d2cdf9f58510c..6885ca024b06a7 100644
--- a/lldb/source/Plugins/Process/Windows/Common/NativeProcessWindows.cpp
+++ b/lldb/source/Plugins/Process/Windows/Common/NativeProcessWindows.cpp
@@ -533,6 +533,9 @@ void NativeProcessWindows::OnExitProcess(uint32_t exit_code) {
bool started = m_session_data && m_session_data->m_initial_stop_received;
ProcessDebugger::OnExitProcess(exit_code);
+ // The exit replaces a stop that has not been reported yet.
+ m_deferred_stop = false;
+
// No signal involved. It is just an exit event.
WaitStatus wait_status(WaitStatus::Exit, exit_code);
SetExitStatus(wait_status, started);
@@ -583,6 +586,29 @@ void NativeProcessWindows::OnDebuggerConnected(lldb::addr_t image_base) {
*this, m_session_data->m_debugger->GetMainThread()));
}
+void NativeProcessWindows::DeferStop() {
+ if (GetState() == eStateStopped) {
+ if (!m_deferred_stop)
+ LLDB_LOG(GetLog(WindowsLog::Exception),
+ "debug event on thread {0:x} while a reported stop is current",
+ GetCurrentThreadID());
+ return;
+ }
+ SetState(eStateStopped, /*notify_delegates=*/false);
+ m_deferred_stop = true;
+ m_deferred_stop_tid = GetCurrentThreadID();
+}
+
+void NativeProcessWindows::ReportDeferredStop() {
+ llvm::sys::ScopedLock lock(m_mutex);
+ if (!m_deferred_stop)
+ return;
+ m_deferred_stop = false;
+ if (GetThreadByID(m_deferred_stop_tid))
+ SetCurrentThreadID(m_deferred_stop_tid);
+ SynchronouslyNotifyProcessStateChanged(eStateStopped);
+}
+
bool NativeProcessWindows::RewindTrapOfRemovedBreakpoint(
const ExceptionRecord &record) {
if (!m_initial_stop_seen)
@@ -646,7 +672,7 @@ NativeProcessWindows::HandleSingleStepException(const ExceptionRecord &record) {
StopThread(record.GetThreadID(), StopReason::eStopReasonTrace);
}
- SetState(eStateStopped, true);
+ DeferStop();
return ExceptionResult::MaskException;
}
@@ -665,7 +691,7 @@ NativeProcessWindows::HandleBreakpointException(const ExceptionRecord &record) {
StopThread(thread_id, StopReason::eStopReasonBreakpoint);
// The current PC is AFTER the BP opcode, on all architectures.
reg_ctx.SetPC(reg_ctx.GetPC() - GetSoftwareBreakpointPCOffset());
- SetState(eStateStopped, true);
+ DeferStop();
return ExceptionResult::MaskException;
}
@@ -692,7 +718,7 @@ NativeProcessWindows::HandleBreakpointException(const ExceptionRecord &record) {
exception_addr)
.str();
StopThread(thread_id, StopReason::eStopReasonWatchpoint, desc);
- SetState(eStateStopped, true);
+ DeferStop();
return ExceptionResult::MaskException;
}
}
@@ -750,7 +776,7 @@ NativeProcessWindows::HandleBreakpointException(const ExceptionRecord &record) {
SetCurrentThreadID(thread_id);
if (NativeThreadWindows *injected = GetThreadByID(thread_id))
injected->SetStopReason(signal_info, "interrupt");
- SetState(eStateStopped, true);
+ DeferStop();
return ExceptionResult::BreakInDebugger;
}
@@ -767,7 +793,7 @@ NativeProcessWindows::HandleBreakpointException(const ExceptionRecord &record) {
record.GetExceptionValue(), exception_addr)
.str();
StopThread(thread_id, StopReason::eStopReasonException, std::move(desc));
- SetState(eStateStopped, true);
+ DeferStop();
return ExceptionResult::MaskException;
}
@@ -793,7 +819,7 @@ NativeProcessWindows::HandleGenericException(bool first_chance,
StopThread(record.GetThreadID(), StopReason::eStopReasonException,
std::move(desc));
- SetState(eStateStopped, true);
+ DeferStop();
return ExceptionResult::BreakInDebugger;
}
diff --git a/lldb/source/Plugins/Process/Windows/Common/NativeProcessWindows.h b/lldb/source/Plugins/Process/Windows/Common/NativeProcessWindows.h
index e79596fecc9f80..79046dd6846a46 100644
--- a/lldb/source/Plugins/Process/Windows/Common/NativeProcessWindows.h
+++ b/lldb/source/Plugins/Process/Windows/Common/NativeProcessWindows.h
@@ -140,6 +140,8 @@ class NativeProcessWindows : public NativeProcessProtocol,
lldb::tid_t thread_id) override;
void OnDebugString(lldb::addr_t debug_string_addr, bool is_unicode,
uint16_t length_lower_word) override;
+ bool HasDeferredStop() const { return m_deferred_stop; }
+ void ReportDeferredStop();
protected:
NativeThreadWindows *GetThreadByID(lldb::tid_t thread_id);
@@ -167,6 +169,9 @@ class NativeProcessWindows : public NativeProcessProtocol,
NativeProcessWindows(lldb::pid_t pid, int terminal_fd,
NativeDelegate &delegate, llvm::Error &E);
+ /// Stop the process without notifying the delegate yet.
+ void DeferStop();
+
/// A breakpoint trap whose debug event was only delivered after the client
/// removed that breakpoint: the thread executed the trap before the stop
/// that removed it, but its event was held back until it ran again. Moves
@@ -196,6 +201,14 @@ class NativeProcessWindows : public NativeProcessProtocol,
/// Set when Halt() / Interrupt() schedules a DebugBreakProcess injection.
bool m_pending_halt = false;
+ /// Set by DeferStop(), cleared once the stop is reported or the process
+ /// exits.
+ bool m_deferred_stop = false;
+
+ /// The thread whose debug event started the deferred stop. Reported as the
+ /// stop's thread even if later events made another thread current.
+ lldb::tid_t m_deferred_stop_tid = LLDB_INVALID_THREAD_ID;
+
bool m_client_supports_libraries_read = false;
/// PseudoConsole for the lldb-server stdio-forwarding path.
@@ -264,6 +277,10 @@ class NativeDebugDelegate : public IDebugDelegate {
return m_process.OnDebuggerError(error, type);
}
+ bool HasDeferredStop() override { return m_process.HasDeferredStop(); }
+
+ void ReportDeferredStop() override { m_process.ReportDeferredStop(); }
+
private:
NativeProcessWindows &m_process;
};
>From b5599c7d8bdc58f032f31cd055f5c30517daf4f0 Mon Sep 17 00:00:00 2001
From: Charles Zablit <c_zablit at apple.com>
Date: Tue, 13 Oct 2026 14:16:12 +0100
Subject: [PATCH 2/2] [lldb][Windows] Report a single step whose trap is still
queued at a stop
---
.../Windows/Common/NativeProcessWindows.cpp | 27 +++++++++++++++++--
.../Windows/Common/NativeThreadWindows.cpp | 17 +++++++++++-
.../Windows/Common/NativeThreadWindows.h | 13 ++++++++-
.../backtrace/TestThreadBacktraceRepeat.py | 2 --
.../hello_watchlocation/TestWatchLocation.py | 1 -
.../thread/num_threads/TestNumThreads.py | 1 -
.../thread/step_out/TestThreadStepOut.py | 13 ++++-----
.../watchlocation/TestSetWatchlocation.py | 1 -
.../stopped-events/TestDAP_stopped_events.py | 8 +++++-
.../TestGdbRemoteThreadsInStopReply.py | 1 -
10 files changed, 67 insertions(+), 17 deletions(-)
diff --git a/lldb/source/Plugins/Process/Windows/Common/NativeProcessWindows.cpp b/lldb/source/Plugins/Process/Windows/Common/NativeProcessWindows.cpp
index 6885ca024b06a7..03bc2d2f5ccefb 100644
--- a/lldb/source/Plugins/Process/Windows/Common/NativeProcessWindows.cpp
+++ b/lldb/source/Plugins/Process/Windows/Common/NativeProcessWindows.cpp
@@ -604,6 +604,16 @@ void NativeProcessWindows::ReportDeferredStop() {
if (!m_deferred_stop)
return;
m_deferred_stop = false;
+ for (const auto &t : m_threads) {
+ auto *thread = static_cast<NativeThreadWindows *>(t.get());
+ if (thread->CompleteStepWithoutTrap()) {
+ LLDB_LOG(GetLog(WindowsLog::Exception),
+ "thread {0:x} completed its single step but its trap is not in "
+ "yet, reporting the step",
+ thread->GetID());
+ SetStopReasonForThread(*thread, StopReason::eStopReasonTrace);
+ }
+ }
if (GetThreadByID(m_deferred_stop_tid))
SetCurrentThreadID(m_deferred_stop_tid);
SynchronouslyNotifyProcessStateChanged(eStateStopped);
@@ -639,10 +649,13 @@ bool NativeProcessWindows::RewindTrapOfRemovedBreakpoint(
ExceptionResult
NativeProcessWindows::HandleSingleStepException(const ExceptionRecord &record) {
+ NativeThreadWindows *stepped_thread = GetThreadByID(record.GetThreadID());
+ const bool step_reported =
+ stepped_thread && stepped_thread->TakePendingStepTrap();
uint32_t wp_id = LLDB_INVALID_INDEX32;
#ifndef __aarch64__
Log *log = GetLog(WindowsLog::Exception);
- if (NativeThreadWindows *thread = GetThreadByID(record.GetThreadID())) {
+ if (NativeThreadWindows *thread = stepped_thread) {
NativeRegisterContextWindows ®_ctx = thread->GetRegisterContext();
Status error =
reg_ctx.GetWatchpointHitIndex(wp_id, record.GetExceptionAddress());
@@ -661,7 +674,17 @@ NativeProcessWindows::HandleSingleStepException(const ExceptionRecord &record) {
}
#endif
if (wp_id == LLDB_INVALID_INDEX32) {
- NativeThreadWindows *thread = GetThreadByID(record.GetThreadID());
+ NativeThreadWindows *thread = stepped_thread;
+ if (step_reported) {
+ LLDB_LOG(GetLog(WindowsLog::Exception),
+ "dropping the trap of the single step thread {0:x} already "
+ "reported",
+ record.GetThreadID());
+ // Re-arm the current step in case this trap consumed its trace flag.
+ if (thread->IsSingleStepping())
+ thread->SetSingleStepFlag();
+ return ExceptionResult::MaskException;
+ }
if (thread && !thread->IsSingleStepping()) {
LLDB_LOG(GetLog(WindowsLog::Exception),
"ignoring a late single-step trap on thread {0:x}, which this "
diff --git a/lldb/source/Plugins/Process/Windows/Common/NativeThreadWindows.cpp b/lldb/source/Plugins/Process/Windows/Common/NativeThreadWindows.cpp
index eeba7d186e34ba..84e25584684f3e 100644
--- a/lldb/source/Plugins/Process/Windows/Common/NativeThreadWindows.cpp
+++ b/lldb/source/Plugins/Process/Windows/Common/NativeThreadWindows.cpp
@@ -51,8 +51,11 @@ Status NativeThreadWindows::DoResume(lldb::StateType resume_state) {
if (resume_state == current_state)
return Status();
- if (resume_state == eStateStepping)
+ lldb::addr_t step_start_pc = LLDB_INVALID_ADDRESS;
+ if (resume_state == eStateStepping) {
+ step_start_pc = GetRegisterContext().GetPC(LLDB_INVALID_ADDRESS);
SetSingleStepFlag();
+ }
if (resume_state == eStateStepping || resume_state == eStateRunning) {
// Clear any stop info left over from a previous stop.
@@ -73,6 +76,7 @@ Status NativeThreadWindows::DoResume(lldb::StateType resume_state) {
} while (previous_suspend_count > 1);
m_state = eStateRunning;
m_single_stepping = resume_state == eStateStepping;
+ m_step_start_pc = step_start_pc;
}
return Status();
@@ -104,6 +108,17 @@ void NativeThreadWindows::SetSingleStepFlag() {
GetRegisterContext().WriteRegisterFromUnsigned(flags_index, flags_value);
}
+bool NativeThreadWindows::CompleteStepWithoutTrap() {
+ lldb::addr_t start_pc = std::exchange(m_step_start_pc, LLDB_INVALID_ADDRESS);
+ if (start_pc == LLDB_INVALID_ADDRESS ||
+ (m_stop_info.reason != eStopReasonInvalid &&
+ m_stop_info.reason != eStopReasonNone) ||
+ GetRegisterContext().GetPC(start_pc) == start_pc)
+ return false;
+ m_step_trap_pending = true;
+ return true;
+}
+
std::string NativeThreadWindows::GetName() {
Log *log = GetLog(LLDBLog::Thread);
static LazyImport<HRESULT(WINAPI *)(HANDLE, PWSTR *)>
diff --git a/lldb/source/Plugins/Process/Windows/Common/NativeThreadWindows.h b/lldb/source/Plugins/Process/Windows/Common/NativeThreadWindows.h
index c594ae03637414..916a7e04e2ce8c 100644
--- a/lldb/source/Plugins/Process/Windows/Common/NativeThreadWindows.h
+++ b/lldb/source/Plugins/Process/Windows/Common/NativeThreadWindows.h
@@ -28,11 +28,20 @@ class NativeThreadWindows : public NativeThreadProtocol {
Status DoStop();
Status DoResume(lldb::StateType resume_state);
- /// Whether the current resume single-steps this thread.
+ /// Whether the last DoResume() single-stepped this thread.
bool IsSingleStepping() const { return m_single_stepping; }
+ /// Called when a stop is reported. Returns true if the single step of the
+ /// last DoResume() moved the PC but its trap was not handled: the kernel
+ /// holds that trap until the thread runs again.
+ bool CompleteStepWithoutTrap();
+
void ClearSingleStepping() { m_single_stepping = false; }
+ bool TakePendingStepTrap() {
+ return std::exchange(m_step_trap_pending, false);
+ }
+
void SetSingleStepFlag();
std::string GetName() override;
@@ -65,6 +74,8 @@ class NativeThreadWindows : public NativeThreadProtocol {
lldb::StateType m_state = lldb::StateType::eStateInvalid;
std::string m_name;
bool m_single_stepping = false;
+ lldb::addr_t m_step_start_pc = LLDB_INVALID_ADDRESS;
+ bool m_step_trap_pending = false;
std::unique_ptr<NativeRegisterContextWindows> m_reg_context_up;
// Cache address and index of the watchpoints and hardware breakpoints since
// the register context does not.
diff --git a/lldb/test/API/commands/thread/backtrace/TestThreadBacktraceRepeat.py b/lldb/test/API/commands/thread/backtrace/TestThreadBacktraceRepeat.py
index 50ed9dfe1b31c9..7eb1f116a772be 100644
--- a/lldb/test/API/commands/thread/backtrace/TestThreadBacktraceRepeat.py
+++ b/lldb/test/API/commands/thread/backtrace/TestThreadBacktraceRepeat.py
@@ -128,8 +128,6 @@ def check_two_threads(
# the comments whether it was getting two threads to the same breakpoint that was
# problematic, or the step-out part. This test stops at the rendevous point so I'm
# removing the skipIfLinux to see if we see any flakiness in just this part of the test.
- @skipIfWindows # This test will hang on windows llvm.org/pr21753
- @expectedFailureAll(oslist=["windows"])
@expectedFailureNetBSD
def test_thread_backtrace_two_threads(self):
"""Test that repeat works even when backtracing on more than one thread."""
diff --git a/lldb/test/API/commands/watchpoints/hello_watchlocation/TestWatchLocation.py b/lldb/test/API/commands/watchpoints/hello_watchlocation/TestWatchLocation.py
index bce56ce6e79e45..8986fd6fa88d28 100644
--- a/lldb/test/API/commands/watchpoints/hello_watchlocation/TestWatchLocation.py
+++ b/lldb/test/API/commands/watchpoints/hello_watchlocation/TestWatchLocation.py
@@ -43,7 +43,6 @@ def affected_by_radar_93863107(self):
@expectedFailureAll(triple=re.compile("^mips"))
# SystemZ and PowerPC also currently supports only one H/W watchpoint
@expectedFailureAll(archs=["powerpc64le", "s390x"])
- @skipIfWindows # This test is flaky on Windows
def test_hello_watchlocation(self):
"""Test watching a location with '-s size' option."""
self.build(dictionary=self.d)
diff --git a/lldb/test/API/functionalities/thread/num_threads/TestNumThreads.py b/lldb/test/API/functionalities/thread/num_threads/TestNumThreads.py
index 93ca5c88fa35b1..2787c751693e47 100644
--- a/lldb/test/API/functionalities/thread/num_threads/TestNumThreads.py
+++ b/lldb/test/API/functionalities/thread/num_threads/TestNumThreads.py
@@ -71,7 +71,6 @@ def test_number_of_threads(self):
)
@skipIfDarwin # rdar://33462362
- @skipIfWindows # This is flakey on Windows: llvm.org/pr37658, llvm.org/pr38373
def test_unique_stacks(self):
"""Test backtrace unique with multiple threads executing the same stack."""
self.build()
diff --git a/lldb/test/API/functionalities/thread/step_out/TestThreadStepOut.py b/lldb/test/API/functionalities/thread/step_out/TestThreadStepOut.py
index a7e7b43a398c5e..3f6f62ba742d58 100644
--- a/lldb/test/API/functionalities/thread/step_out/TestThreadStepOut.py
+++ b/lldb/test/API/functionalities/thread/step_out/TestThreadStepOut.py
@@ -11,16 +11,17 @@
@requireThreadSupport
class ThreadStepOutTestCase(TestBase):
- @skipIfWindows # This test will hang on windows llvm.org/pr21753
- @expectedFailureAll(oslist=["windows"])
@expectedFailureNetBSD
def test_step_single_thread(self):
"""Test thread step out on one thread via command interpreter."""
self.build()
self.step_out_test(self.step_out_single_thread_with_cmd)
- @skipIfWindows # This test will hang on windows llvm.org/pr21753
- @expectedFailureAll(oslist=["windows"])
+ # The in-process Windows plugin (ProcessWindows) reports one thread's
+ # exception per stop. When both threads trap together, the other thread's
+ # event only arrives after the next resume, so the step-out ends on that
+ # thread's trace or with no stop reason, differently from run to run.
+ @skipIfWindowsAndNoLLDBServer
@expectedFailureAll(
oslist=["watchos"], archs=["armv7k"], bugnumber="rdar://problem/34674488"
) # stop reason is trace when it should be step-out
@@ -30,8 +31,8 @@ def test_step_all_threads(self):
self.build()
self.step_out_test(self.step_out_all_threads_with_cmd)
- @skipIfWindows # This test will hang on windows llvm.org/pr21753
- @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24681")
+ # Same in-process Windows limitation as test_step_all_threads.
+ @skipIfWindowsAndNoLLDBServer
@expectedFailureNetBSD
def test_python(self):
"""Test thread step out on one thread via Python API (dwarf)."""
diff --git a/lldb/test/API/python_api/watchpoint/watchlocation/TestSetWatchlocation.py b/lldb/test/API/python_api/watchpoint/watchlocation/TestSetWatchlocation.py
index ce8e06c5dacf48..fc1061060a47fb 100644
--- a/lldb/test/API/python_api/watchpoint/watchlocation/TestSetWatchlocation.py
+++ b/lldb/test/API/python_api/watchpoint/watchlocation/TestSetWatchlocation.py
@@ -22,7 +22,6 @@ def setUp(self):
# This is for verifying that watch location works.
self.violating_func = "do_bad_thing_with_location"
- @skipIfWindows # This test is flaky on Windows
def test_watch_location(self):
"""Exercise SBValue.WatchPointee() API to set a watchpoint."""
self.build()
diff --git a/lldb/test/API/tools/lldb-dap/stopped-events/TestDAP_stopped_events.py b/lldb/test/API/tools/lldb-dap/stopped-events/TestDAP_stopped_events.py
index a1fd2347b82289..8e4a7386f259e9 100644
--- a/lldb/test/API/tools/lldb-dap/stopped-events/TestDAP_stopped_events.py
+++ b/lldb/test/API/tools/lldb-dap/stopped-events/TestDAP_stopped_events.py
@@ -10,7 +10,13 @@
from lldbsuite.test.tools.lldb_dap.types import LaunchArgs, StoppedEvent, ThreadsArgs
- at skipIfWindows # This is flakey on Windows: llvm.org/pr24668, llvm.org/pr38373
+# Needs both threads' breakpoint hits in one stop.
+# The in-process Windows plugin (ProcessWindows) reports one thread's exception
+# per stop.
+# lldb-server puts every hit that is already queued into the one stop, but
+# on a loaded machine the second thread can reach the trap only after the stop
+# was reported, so it still flakes there.
+ at skipIfWindows
@skipIfLinux
@requireThreadSupport
class TestDAP_stopped_events(DAPTestCaseBase):
diff --git a/lldb/test/API/tools/lldb-server/TestGdbRemoteThreadsInStopReply.py b/lldb/test/API/tools/lldb-server/TestGdbRemoteThreadsInStopReply.py
index dc0c62bd375028..8578c191d0d48e 100644
--- a/lldb/test/API/tools/lldb-server/TestGdbRemoteThreadsInStopReply.py
+++ b/lldb/test/API/tools/lldb-server/TestGdbRemoteThreadsInStopReply.py
@@ -254,7 +254,6 @@ def classify(thread_info):
self.assertTrue(saw_stopped, "no jThreadsInfo entry for the stopped thread")
@skipIfNetBSD
- @skipIfWindows # Flaky on Windows
def test_stop_reply_contains_thread_pcs(self):
self.build()
self.set_inferior_startup_launch()
More information about the lldb-commits
mailing list