[Lldb-commits] [lldb] [lldb][Windows] Enable the multithreaded and multiple-debuggers API tests (PR #224305)
Charles Zablit via lldb-commits
lldb-commits at lists.llvm.org
Mon Sep 21 08:48:43 PDT 2026
https://github.com/charles-zablit updated https://github.com/llvm/llvm-project/pull/224305
>From 7aa5d1d4aefeb9826607e3dcfdd8547be61e474e Mon Sep 17 00:00:00 2001
From: Charles Zablit <c_zablit at apple.com>
Date: Thu, 17 Sep 2026 14:40:49 +0100
Subject: [PATCH 1/2] [lldb][Windows] Enable the multithreaded and
multiple-debuggers API tests
---
.../TestMultipleDebuggers.py | 1 -
.../multi-process-driver.cpp | 2 ++
.../api/multithreaded/TestMultithreaded.py | 16 ++---------
lldb/test/API/api/multithreaded/common.h | 28 +++++++++++++++----
.../API/api/multithreaded/listener_test.cpp | 6 ++--
.../test_breakpoint_callback.cpp | 4 +--
.../test_breakpoint_location_callback.cpp | 4 +--
.../API/api/multithreaded/test_stop-hook.cpp | 15 ++++++++++
8 files changed, 48 insertions(+), 28 deletions(-)
diff --git a/lldb/test/API/api/multiple-debuggers/TestMultipleDebuggers.py b/lldb/test/API/api/multiple-debuggers/TestMultipleDebuggers.py
index 13c2f5d961a78..c6010e109c12f 100644
--- a/lldb/test/API/api/multiple-debuggers/TestMultipleDebuggers.py
+++ b/lldb/test/API/api/multiple-debuggers/TestMultipleDebuggers.py
@@ -19,7 +19,6 @@ class TestMultipleSimultaneousDebuggers(TestBase):
# https://github.com/llvm/llvm-project/issues/101162
@skipIfLinux
@skipIfNoSBHeaders
- @skipIfWindows
@skipIfHostIncompatibleWithTarget
def test_multiple_debuggers(self):
self.driver_exe = self.getBuildArtifact("multi-process-driver")
diff --git a/lldb/test/API/api/multiple-debuggers/multi-process-driver.cpp b/lldb/test/API/api/multiple-debuggers/multi-process-driver.cpp
index 5847dc709a771..30af50ba389c4 100644
--- a/lldb/test/API/api/multiple-debuggers/multi-process-driver.cpp
+++ b/lldb/test/API/api/multiple-debuggers/multi-process-driver.cpp
@@ -17,7 +17,9 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#ifndef _WIN32
#include <unistd.h>
+#endif
#include "lldb/API/SBBreakpoint.h"
#include "lldb/API/SBBroadcaster.h"
diff --git a/lldb/test/API/api/multithreaded/TestMultithreaded.py b/lldb/test/API/api/multithreaded/TestMultithreaded.py
index 3a3467936a349..7028b0a135e97 100644
--- a/lldb/test/API/api/multithreaded/TestMultithreaded.py
+++ b/lldb/test/API/api/multithreaded/TestMultithreaded.py
@@ -18,16 +18,13 @@ def setUp(self):
TestBase.setUp(self)
@skipIfRemote
- # clang-cl does not support throw or catch (llvm.org/pr24538)
- @skipIfWindows
+ @skipIfWindows # https://github.com/llvm/llvm-project/issues/224303
@skipIfHostIncompatibleWithTarget
def test_python_stop_hook(self):
"""Test that you can run a python command in a stop-hook when stdin is File based."""
self.build_and_test("driver.cpp test_stop-hook.cpp", "test_python_stop_hook")
@skipIfRemote
- # clang-cl does not support throw or catch (llvm.org/pr24538)
- @skipIfWindows
@skipIfHostIncompatibleWithTarget
def test_breakpoint_callback(self):
"""Test the that SBBreakpoint callback is invoked when a breakpoint is hit."""
@@ -36,8 +33,7 @@ def test_breakpoint_callback(self):
)
@skipIfRemote
- # clang-cl does not support throw or catch (llvm.org/pr24538)
- @skipIfWindows
+ @skipIfWindows # https://github.com/llvm/llvm-project/issues/224303
@skipIfHostIncompatibleWithTarget
def test_breakpoint_location_callback(self):
"""Test the that SBBreakpointLocation callback is invoked when a breakpoint is hit."""
@@ -47,8 +43,6 @@ def test_breakpoint_location_callback(self):
)
@skipIfRemote
- # clang-cl does not support throw or catch (llvm.org/pr24538)
- @skipIfWindows
@expectedFlakeyFreeBSD
@skipIfHostIncompatibleWithTarget
def test_sb_api_listener_event_description(self):
@@ -59,8 +53,6 @@ def test_sb_api_listener_event_description(self):
)
@skipIfRemote
- # clang-cl does not support throw or catch (llvm.org/pr24538)
- @skipIfWindows
@expectedFlakeyFreeBSD
@skipIfHostIncompatibleWithTarget
def test_sb_api_listener_event_process_state(self):
@@ -73,8 +65,6 @@ def test_sb_api_listener_event_process_state(self):
)
@skipIfRemote
- # clang-cl does not support throw or catch (llvm.org/pr24538)
- @skipIfWindows
@expectedFlakeyFreeBSD
@skipIf(oslist=["linux"]) # flakey
@skipIfHostIncompatibleWithTarget
@@ -86,8 +76,6 @@ def test_sb_api_listener_resume(self):
)
@skipIfRemote
- # clang-cl does not support throw or catch (llvm.org/pr24538)
- @skipIfWindows
@skipIfHostIncompatibleWithTarget
def test_concurrent_unwind(self):
"""Test that you can run a python command in a stop-hook when stdin is File based."""
diff --git a/lldb/test/API/api/multithreaded/common.h b/lldb/test/API/api/multithreaded/common.h
index 2ef1cb7c5664d..0df4b771f9550 100644
--- a/lldb/test/API/api/multithreaded/common.h
+++ b/lldb/test/API/api/multithreaded/common.h
@@ -1,15 +1,21 @@
#ifndef LLDB_TEST_API_COMMON_H
#define LLDB_TEST_API_COMMON_H
-#include <condition_variable>
#include <chrono>
+#include <condition_variable>
+#include <cstdlib>
#include <exception>
#include <iostream>
#include <mutex>
-#include <string>
#include <queue>
+#include <string>
+#ifdef _WIN32
+#include <direct.h>
+#include <io.h>
+#else
#include <unistd.h>
+#endif
/// Simple exception class with a message
struct Exception : public std::exception
@@ -56,14 +62,24 @@ class multithreaded_queue {
}
};
-/// Allocates a char buffer with the current working directory
-inline char* get_working_dir() {
+/// Returns the current working directory.
+///
+/// The platform accessors all return a malloc'd buffer, so the result is
+/// copied into a std::string and freed here.
+inline std::string get_working_dir() {
#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || \
defined(__OpenBSD__)
- return getwd(0);
+ char *dir = getwd(0);
+#elif defined(_WIN32)
+ char *dir = _getcwd(0, 0);
#else
- return get_current_dir_name();
+ char *dir = get_current_dir_name();
#endif
+ if (!dir)
+ return std::string();
+ std::string result(dir);
+ free(dir);
+ return result;
}
#endif // LLDB_TEST_API_COMMON_H
diff --git a/lldb/test/API/api/multithreaded/listener_test.cpp b/lldb/test/API/api/multithreaded/listener_test.cpp
index f4f76c6071fb1..b030bf57b93e9 100644
--- a/lldb/test/API/api/multithreaded/listener_test.cpp
+++ b/lldb/test/API/api/multithreaded/listener_test.cpp
@@ -43,16 +43,16 @@ void test(SBDebugger &dbg, std::vector<string> args) {
if (!breakpoint.IsValid())
throw Exception("invalid breakpoint");
- std::unique_ptr<char> working_dir(get_working_dir());
+ std::string working_dir = get_working_dir();
SBError error;
SBProcess process = target.Launch(g_listener, 0, 0, 0, 0, 0,
- working_dir.get(), 0, false, error);
+ working_dir.c_str(), 0, false, error);
if (!error.Success())
throw Exception("Error launching process.");
/* FIXME: the approach below deadlocks
- SBProcess process = target.LaunchSimple (0, 0, working_dir.get());
+ SBProcess process = target.LaunchSimple (0, 0, working_dir.c_str());
// get debugger listener (which is attached to process by default)
g_listener = dbg.GetListener();
diff --git a/lldb/test/API/api/multithreaded/test_breakpoint_callback.cpp b/lldb/test/API/api/multithreaded/test_breakpoint_callback.cpp
index 3b8e909cef434..5cff1cd2b23b6 100644
--- a/lldb/test/API/api/multithreaded/test_breakpoint_callback.cpp
+++ b/lldb/test/API/api/multithreaded/test_breakpoint_callback.cpp
@@ -42,8 +42,8 @@ void test(SBDebugger &dbg, vector<string> args) {
throw Exception("invalid breakpoint");
breakpoint.SetCallback(BPCallback, 0);
- std::unique_ptr<char> working_dir(get_working_dir());
- SBProcess process = target.LaunchSimple(0, 0, working_dir.get());
+ std::string working_dir = get_working_dir();
+ SBProcess process = target.LaunchSimple(0, 0, working_dir.c_str());
{
unique_lock<mutex> lock(g_mutex);
diff --git a/lldb/test/API/api/multithreaded/test_breakpoint_location_callback.cpp b/lldb/test/API/api/multithreaded/test_breakpoint_location_callback.cpp
index eea3b9ed65f24..2a5d9c4270897 100644
--- a/lldb/test/API/api/multithreaded/test_breakpoint_location_callback.cpp
+++ b/lldb/test/API/api/multithreaded/test_breakpoint_location_callback.cpp
@@ -54,8 +54,8 @@ void test(SBDebugger &dbg, vector<string> args) {
SBBreakpointLocation breakpoint_location = breakpoint.GetLocationAtIndex(0);
breakpoint_location.SetCallback(BPCallback, 0);
- std::unique_ptr<char> working_dir(get_working_dir());
- SBProcess process = target.LaunchSimple(0, 0, working_dir.get());
+ std::string working_dir = get_working_dir();
+ SBProcess process = target.LaunchSimple(0, 0, working_dir.c_str());
{
unique_lock<mutex> lock(g_mutex);
diff --git a/lldb/test/API/api/multithreaded/test_stop-hook.cpp b/lldb/test/API/api/multithreaded/test_stop-hook.cpp
index a88892340e613..97121abf98743 100644
--- a/lldb/test/API/api/multithreaded/test_stop-hook.cpp
+++ b/lldb/test/API/api/multithreaded/test_stop-hook.cpp
@@ -4,6 +4,10 @@
#include <cstdlib>
#include <errno.h>
+#ifdef _WIN32
+#include <fcntl.h>
+#include <io.h>
+#endif
#include <mutex>
#include <stdio.h>
#include <string>
@@ -86,9 +90,15 @@ void test(SBDebugger &dbg, std::vector<std::string> args) {
// Now switch the I/O over to a pipe, which will be handled by the
// NativeFile class:
int to_lldb_des[2];
+#ifdef _WIN32
+ int pipe_result = _pipe(to_lldb_des, 4096, _O_TEXT);
+ FILE *fh_lldb_in = _fdopen(to_lldb_des[0], "r");
+ FILE *fh_to_lldb = _fdopen(to_lldb_des[1], "w");
+#else
int pipe_result = pipe(to_lldb_des);
FILE *fh_lldb_in = fdopen(to_lldb_des[0], "r");
FILE *fh_to_lldb = fdopen(to_lldb_des[1], "w");
+#endif
// We need to reset the handle before destroying the debugger
// or the same deadlock will stall exiting:
@@ -101,8 +111,13 @@ void test(SBDebugger &dbg, std::vector<std::string> args) {
}
~Cleanup() {
m_dbg.SetInputFileHandle(m_file, false);
+#ifdef _WIN32
+ _close(m_filedes[0]);
+ _close(m_filedes[1]);
+#else
close(m_filedes[0]);
close(m_filedes[1]);
+#endif
}
private:
>From 3da249c6a018b48aa9ee7b41e4973c1433440312 Mon Sep 17 00:00:00 2001
From: Charles Zablit <c_zablit at apple.com>
Date: Mon, 21 Sep 2026 16:11:19 +0100
Subject: [PATCH 2/2] [lldb][Windows] Build the SB API test drivers against the
DLL CRT
---
.../Python/lldbsuite/test/lldbtest.py | 6 ++++--
.../api/multithreaded/TestMultithreaded.py | 1 -
.../API/api/multithreaded/test_stop-hook.cpp | 19 +++++++------------
3 files changed, 11 insertions(+), 15 deletions(-)
diff --git a/lldb/packages/Python/lldbsuite/test/lldbtest.py b/lldb/packages/Python/lldbsuite/test/lldbtest.py
index bec50f806110b..af8c91d83ac00 100644
--- a/lldb/packages/Python/lldbsuite/test/lldbtest.py
+++ b/lldb/packages/Python/lldbsuite/test/lldbtest.py
@@ -1769,18 +1769,20 @@ def buildDriver(self, sources, exe_name, defines=None):
% (self.lib_lldb, self.framework_dir, lib_dir),
}
elif sys.platform.startswith("win"):
+ crt = "dll_dbg" if configuration.cmake_build_type == "debug" else "dll"
d = {
"CXX_SOURCES": sources,
"EXE": exe_name,
- "CFLAGS_EXTRAS": "%s %s -I%s -I%s %s"
+ "CFLAGS_EXTRAS": "%s %s -fms-runtime-lib=%s -I%s -I%s %s"
% (
stdflag,
stdlibflag,
+ crt,
os.path.join(os.environ["LLDB_SRC"], "include"),
os.path.join(configuration.lldb_obj_root, "include"),
defines,
),
- "LD_EXTRAS": "-L%s -lliblldb" % lib_dir,
+ "LD_EXTRAS": "-L%s -lliblldb -Xlinker -nodefaultlib:libcmt" % lib_dir,
}
else:
d = {
diff --git a/lldb/test/API/api/multithreaded/TestMultithreaded.py b/lldb/test/API/api/multithreaded/TestMultithreaded.py
index 7028b0a135e97..c306fe9b0af75 100644
--- a/lldb/test/API/api/multithreaded/TestMultithreaded.py
+++ b/lldb/test/API/api/multithreaded/TestMultithreaded.py
@@ -18,7 +18,6 @@ def setUp(self):
TestBase.setUp(self)
@skipIfRemote
- @skipIfWindows # https://github.com/llvm/llvm-project/issues/224303
@skipIfHostIncompatibleWithTarget
def test_python_stop_hook(self):
"""Test that you can run a python command in a stop-hook when stdin is File based."""
diff --git a/lldb/test/API/api/multithreaded/test_stop-hook.cpp b/lldb/test/API/api/multithreaded/test_stop-hook.cpp
index 97121abf98743..9c754d131214d 100644
--- a/lldb/test/API/api/multithreaded/test_stop-hook.cpp
+++ b/lldb/test/API/api/multithreaded/test_stop-hook.cpp
@@ -104,28 +104,23 @@ void test(SBDebugger &dbg, std::vector<std::string> args) {
// or the same deadlock will stall exiting:
class Cleanup {
public:
- Cleanup(SBDebugger dbg, int filedes[2]) : m_dbg(dbg) {
+ Cleanup(SBDebugger dbg, FILE *read_end, FILE *write_end)
+ : m_dbg(dbg), m_read_end(read_end), m_write_end(write_end) {
m_file = m_dbg.GetInputFileHandle();
- m_filedes[0] = filedes[0];
- m_filedes[1] = filedes[1];
}
~Cleanup() {
+ fclose(m_write_end);
m_dbg.SetInputFileHandle(m_file, false);
-#ifdef _WIN32
- _close(m_filedes[0]);
- _close(m_filedes[1]);
-#else
- close(m_filedes[0]);
- close(m_filedes[1]);
-#endif
+ fclose(m_read_end);
}
private:
FILE *m_file;
SBDebugger m_dbg;
- int m_filedes[2];
+ FILE *m_read_end;
+ FILE *m_write_end;
};
- Cleanup cleanup(dbg, to_lldb_des);
+ Cleanup cleanup(dbg, fh_lldb_in, fh_to_lldb);
dbg.SetInputFileHandle(fh_lldb_in, false);
More information about the lldb-commits
mailing list