[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