[Lldb-commits] [lldb] [lldb] Multithreading lldb-server works on Windows now; fixed gdb port mapping (PR #100670)

via lldb-commits lldb-commits at lists.llvm.org
Thu Jul 25 16:16:19 PDT 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-lldb

Author: Dmitry Vasilyev (slydiman)

<details>
<summary>Changes</summary>

Removed fork(). Used threads and the common thread-safe port map for all platform connections.

Updated lldb::FileSystem to use llvm::vfs::createPhysicalFileSystem() with an own virtual working directory per thread.

This patch depends on #<!-- -->100659, #<!-- -->100666.

This patch fixes #<!-- -->97537, #<!-- -->90923, #<!-- -->56346.

lldb-server has been tested on Windows with 50 connections and 100 processes launched simultaneously. Tested also the cross build with Linux x86_64 host and Linux Aarch64 target.

---

Patch is 33.09 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/100670.diff


8 Files Affected:

- (modified) lldb/include/lldb/Host/FileSystem.h (+7) 
- (modified) lldb/source/Host/common/FileSystem.cpp (+8) 
- (modified) lldb/source/Host/posix/PipePosix.cpp (+12) 
- (modified) lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp (+13-2) 
- (modified) lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp (+217-92) 
- (modified) lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.h (+19-12) 
- (modified) lldb/tools/lldb-server/LLDBServerUtilities.cpp (+2) 
- (modified) lldb/tools/lldb-server/lldb-platform.cpp (+22-77) 


``````````diff
diff --git a/lldb/include/lldb/Host/FileSystem.h b/lldb/include/lldb/Host/FileSystem.h
index 640f3846e448c..5e25414a894d3 100644
--- a/lldb/include/lldb/Host/FileSystem.h
+++ b/lldb/include/lldb/Host/FileSystem.h
@@ -47,6 +47,12 @@ class FileSystem {
 
   static FileSystem &Instance();
 
+  static void InitializePerThread() {
+    lldbassert(!InstancePerThread() && "Already initialized.");
+    InstancePerThread().emplace(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem>(
+        llvm::vfs::createPhysicalFileSystem().release()));
+  }
+
   template <class... T> static void Initialize(T &&...t) {
     lldbassert(!InstanceImpl() && "Already initialized.");
     InstanceImpl().emplace(std::forward<T>(t)...);
@@ -206,6 +212,7 @@ class FileSystem {
 
 private:
   static std::optional<FileSystem> &InstanceImpl();
+  static std::optional<FileSystem> &InstancePerThread();
   llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> m_fs;
   std::unique_ptr<TildeExpressionResolver> m_tilde_resolver;
   std::string m_home_directory;
diff --git a/lldb/source/Host/common/FileSystem.cpp b/lldb/source/Host/common/FileSystem.cpp
index 5153a0a9ec513..cb76086616d6b 100644
--- a/lldb/source/Host/common/FileSystem.cpp
+++ b/lldb/source/Host/common/FileSystem.cpp
@@ -49,7 +49,15 @@ void FileSystem::Terminate() {
   InstanceImpl().reset();
 }
 
+std::optional<FileSystem> &FileSystem::InstancePerThread() {
+  static thread_local std::optional<FileSystem> t_fs;
+  return t_fs;
+}
+
 std::optional<FileSystem> &FileSystem::InstanceImpl() {
+  std::optional<FileSystem> &fs = InstancePerThread();
+  if (fs)
+    return fs;
   static std::optional<FileSystem> g_fs;
   return g_fs;
 }
diff --git a/lldb/source/Host/posix/PipePosix.cpp b/lldb/source/Host/posix/PipePosix.cpp
index f35c348990df6..1aa02efe86610 100644
--- a/lldb/source/Host/posix/PipePosix.cpp
+++ b/lldb/source/Host/posix/PipePosix.cpp
@@ -324,6 +324,18 @@ Status PipePosix::ReadWithTimeout(void *buf, size_t size,
         bytes_read += result;
         if (bytes_read == size || result == 0)
           break;
+
+        // This is the workaround for the following bug in Linux multithreading
+        // select() https://bugzilla.kernel.org/show_bug.cgi?id=546
+        // ReadWithTimeout() with a non-zero timeout is used only to
+        // read the port number from the gdbserver pipe
+        // in GDBRemoteCommunication::StartDebugserverProcess().
+        // The port number may be "1024\0".."65535\0".
+        if (timeout.count() > 0 && size == 6 && bytes_read == 5 &&
+            static_cast<char *>(buf)[4] == '\0') {
+          break;
+        }
+
       } else if (errno == EINTR) {
         continue;
       } else {
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp
index f9d37490e16ae..cef836e001adf 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp
@@ -646,7 +646,9 @@ GDBRemoteCommunicationServerCommon::Handle_vFile_Size(
   packet.GetHexByteString(path);
   if (!path.empty()) {
     uint64_t Size;
-    if (llvm::sys::fs::file_size(path, Size))
+    FileSpec file_spec(path);
+    FileSystem::Instance().Resolve(file_spec);
+    if (llvm::sys::fs::file_size(file_spec.GetPath(), Size))
       return SendErrorResponse(5);
     StreamString response;
     response.PutChar('F');
@@ -725,7 +727,9 @@ GDBRemoteCommunicationServerCommon::Handle_vFile_unlink(
   packet.SetFilePos(::strlen("vFile:unlink:"));
   std::string path;
   packet.GetHexByteString(path);
-  Status error(llvm::sys::fs::remove(path));
+  FileSpec file_spec(path);
+  FileSystem::Instance().Resolve(file_spec);
+  Status error(llvm::sys::fs::remove(file_spec.GetPath()));
   StreamString response;
   response.Printf("F%x,%x", error.GetError(), error.GetError());
   return SendPacketNoLock(response.GetString());
@@ -744,6 +748,13 @@ GDBRemoteCommunicationServerCommon::Handle_qPlatform_shell(
       // uint32_t timeout = packet.GetHexMaxU32(false, 32);
       if (packet.GetChar() == ',')
         packet.GetHexByteString(working_dir);
+      else {
+        auto cwd = FileSystem::Instance()
+                       .GetVirtualFileSystem()
+                       ->getCurrentWorkingDirectory();
+        if (cwd)
+          working_dir = *cwd;
+      }
       int status, signo;
       std::string output;
       FileSpec working_spec(working_dir);
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp
index 65f1cc12ba307..6e3b7b4a351e0 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp
@@ -18,13 +18,13 @@
 #include <sstream>
 #include <thread>
 
-#include "llvm/Support/FileSystem.h"
 #include "llvm/Support/JSON.h"
 #include "llvm/Support/Threading.h"
 
 #include "lldb/Host/Config.h"
 #include "lldb/Host/ConnectionFileDescriptor.h"
 #include "lldb/Host/FileAction.h"
+#include "lldb/Host/FileSystem.h"
 #include "lldb/Host/Host.h"
 #include "lldb/Host/HostInfo.h"
 #include "lldb/Interpreter/CommandCompletions.h"
@@ -44,8 +44,17 @@ using namespace lldb;
 using namespace lldb_private::process_gdb_remote;
 using namespace lldb_private;
 
+// Copy assignment operator to avoid copying m_mutex
+GDBRemoteCommunicationServerPlatform::PortMap &
+GDBRemoteCommunicationServerPlatform::PortMap::operator=(
+    const GDBRemoteCommunicationServerPlatform::PortMap &o) {
+  m_port_map = std::move(o.m_port_map);
+  return *this;
+}
+
 GDBRemoteCommunicationServerPlatform::PortMap::PortMap(uint16_t min_port,
-                                                       uint16_t max_port) {
+                                                       uint16_t max_port)
+    : m_mutex() {
   assert(min_port);
   for (; min_port < max_port; ++min_port)
     m_port_map[min_port] = LLDB_INVALID_PROCESS_ID;
@@ -54,11 +63,13 @@ GDBRemoteCommunicationServerPlatform::PortMap::PortMap(uint16_t min_port,
 void GDBRemoteCommunicationServerPlatform::PortMap::AllowPort(uint16_t port) {
   assert(port);
   // Do not modify existing mappings
+  std::lock_guard<std::mutex> guard(m_mutex);
   m_port_map.insert({port, LLDB_INVALID_PROCESS_ID});
 }
 
 llvm::Expected<uint16_t>
 GDBRemoteCommunicationServerPlatform::PortMap::GetNextAvailablePort() {
+  std::lock_guard<std::mutex> guard(m_mutex);
   if (m_port_map.empty())
     return 0; // Bind to port zero and get a port, we didn't have any
               // limitations
@@ -75,6 +86,7 @@ GDBRemoteCommunicationServerPlatform::PortMap::GetNextAvailablePort() {
 
 bool GDBRemoteCommunicationServerPlatform::PortMap::AssociatePortWithProcess(
     uint16_t port, lldb::pid_t pid) {
+  std::lock_guard<std::mutex> guard(m_mutex);
   auto pos = m_port_map.find(port);
   if (pos != m_port_map.end()) {
     pos->second = pid;
@@ -84,6 +96,7 @@ bool GDBRemoteCommunicationServerPlatform::PortMap::AssociatePortWithProcess(
 }
 
 bool GDBRemoteCommunicationServerPlatform::PortMap::FreePort(uint16_t port) {
+  std::lock_guard<std::mutex> guard(m_mutex);
   std::map<uint16_t, lldb::pid_t>::iterator pos = m_port_map.find(port);
   if (pos != m_port_map.end()) {
     pos->second = LLDB_INVALID_PROCESS_ID;
@@ -94,6 +107,7 @@ bool GDBRemoteCommunicationServerPlatform::PortMap::FreePort(uint16_t port) {
 
 bool GDBRemoteCommunicationServerPlatform::PortMap::FreePortForProcess(
     lldb::pid_t pid) {
+  std::lock_guard<std::mutex> guard(m_mutex);
   if (!m_port_map.empty()) {
     for (auto &pair : m_port_map) {
       if (pair.second == pid) {
@@ -106,15 +120,22 @@ bool GDBRemoteCommunicationServerPlatform::PortMap::FreePortForProcess(
 }
 
 bool GDBRemoteCommunicationServerPlatform::PortMap::empty() const {
+  std::lock_guard<std::mutex> guard(m_mutex);
   return m_port_map.empty();
 }
 
+GDBRemoteCommunicationServerPlatform::PortMap
+    GDBRemoteCommunicationServerPlatform::g_port_map;
+std::set<lldb::pid_t> GDBRemoteCommunicationServerPlatform::g_spawned_pids;
+std::mutex GDBRemoteCommunicationServerPlatform::g_spawned_pids_mutex;
+
 // GDBRemoteCommunicationServerPlatform constructor
 GDBRemoteCommunicationServerPlatform::GDBRemoteCommunicationServerPlatform(
-    const Socket::SocketProtocol socket_protocol, const char *socket_scheme)
-    : GDBRemoteCommunicationServerCommon(),
-      m_socket_protocol(socket_protocol), m_socket_scheme(socket_scheme),
-      m_spawned_pids_mutex(), m_port_map(), m_port_offset(0) {
+    const Socket::SocketProtocol socket_protocol, const char *socket_scheme,
+    const lldb_private::Args &args, uint16_t port_offset)
+    : GDBRemoteCommunicationServerCommon(), m_socket_protocol(socket_protocol),
+      m_socket_scheme(socket_scheme), m_inferior_arguments(args),
+      m_port_offset(port_offset) {
   m_pending_gdb_server.pid = LLDB_INVALID_PROCESS_ID;
   m_pending_gdb_server.port = 0;
 
@@ -159,11 +180,72 @@ GDBRemoteCommunicationServerPlatform::GDBRemoteCommunicationServerPlatform(
 GDBRemoteCommunicationServerPlatform::~GDBRemoteCommunicationServerPlatform() =
     default;
 
+lldb::thread_result_t GDBRemoteCommunicationServerPlatform::ThreadProc() {
+  // We need a virtual working directory per thread.
+  FileSystem::InitializePerThread();
+
+  Log *log = GetLog(LLDBLog::Platform);
+
+  if (IsConnected()) {
+    LLDB_LOGF(log,
+              "GDBRemoteCommunicationServerPlatform::%s() "
+              "Thread started...",
+              __FUNCTION__);
+
+    if (m_inferior_arguments.GetArgumentCount() > 0) {
+      lldb::pid_t pid = LLDB_INVALID_PROCESS_ID;
+      std::optional<uint16_t> port;
+      std::string socket_name;
+      Status error = LaunchGDBServer(m_inferior_arguments,
+                                     "", // hostname
+                                     pid, port, socket_name);
+      if (error.Success())
+        SetPendingGdbServer(pid, *port, socket_name);
+    }
+
+    bool interrupt = false;
+    bool done = false;
+    Status error;
+    while (!interrupt && !done) {
+      if (GetPacketAndSendResponse(std::nullopt, error, interrupt, done) !=
+          GDBRemoteCommunication::PacketResult::Success)
+        break;
+    }
+
+    if (error.Fail()) {
+      LLDB_LOGF(log,
+                "GDBRemoteCommunicationServerPlatform::%s() "
+                "GetPacketAndSendResponse: %s",
+                __FUNCTION__, error.AsCString());
+    }
+  }
+
+  LLDB_LOGF(log,
+            "GDBRemoteCommunicationServerPlatform::%s() "
+            "Disconnected. Killing child processes...",
+            __FUNCTION__);
+  for (lldb::pid_t pid : m_spawned_pids)
+    KillSpawnedProcess(pid);
+
+  // Do do not wait for child processes. See comments in
+  // DebugserverProcessReaped() for details.
+
+  FileSystem::Terminate();
+
+  LLDB_LOGF(log,
+            "GDBRemoteCommunicationServerPlatform::%s() "
+            "Thread exited.",
+            __FUNCTION__);
+
+  delete this;
+  return {};
+}
+
 Status GDBRemoteCommunicationServerPlatform::LaunchGDBServer(
     const lldb_private::Args &args, std::string hostname, lldb::pid_t &pid,
     std::optional<uint16_t> &port, std::string &socket_name) {
   if (!port) {
-    llvm::Expected<uint16_t> available_port = m_port_map.GetNextAvailablePort();
+    llvm::Expected<uint16_t> available_port = g_port_map.GetNextAvailablePort();
     if (available_port)
       port = *available_port;
     else
@@ -181,23 +263,25 @@ Status GDBRemoteCommunicationServerPlatform::LaunchGDBServer(
   if (hostname.empty())
     hostname = "127.0.0.1";
 
-  Log *log = GetLog(LLDBLog::Platform);
-  LLDB_LOGF(log, "Launching debugserver with: %s:%u...", hostname.c_str(),
-            *port);
+  auto cwd = FileSystem::Instance()
+                 .GetVirtualFileSystem()
+                 ->getCurrentWorkingDirectory();
+  if (cwd)
+    debugserver_launch_info.SetWorkingDirectory(FileSpec(*cwd));
 
   // Do not run in a new session so that it can not linger after the platform
   // closes.
   debugserver_launch_info.SetLaunchInSeparateProcessGroup(false);
   debugserver_launch_info.SetMonitorProcessCallback(
-      std::bind(&GDBRemoteCommunicationServerPlatform::DebugserverProcessReaped,
-                this, std::placeholders::_1));
+      &GDBRemoteCommunicationServerPlatform::DebugserverProcessReaped);
 
   std::ostringstream url;
 // debugserver does not accept the URL scheme prefix.
 #if !defined(__APPLE__)
   url << m_socket_scheme << "://";
 #endif
-  uint16_t *port_ptr = &*port;
+  uint16_t child_port = *port;
+  uint16_t *port_ptr = &child_port;
   if (m_socket_protocol == Socket::ProtocolTcp) {
     std::string platform_uri = GetConnection()->GetURI();
     std::optional<URI> parsed_uri = URI::Parse(platform_uri);
@@ -208,19 +292,44 @@ Status GDBRemoteCommunicationServerPlatform::LaunchGDBServer(
     port_ptr = nullptr;
   }
 
+  Log *log = GetLog(LLDBLog::Platform);
+  LLDB_LOGF(log,
+            "GDBRemoteCommunicationServerPlatform::%s() "
+            "Host %s launching debugserver with: %s...",
+            __FUNCTION__, hostname.c_str(), url.str().c_str());
+
   Status error = StartDebugserverProcess(
       url.str().c_str(), nullptr, debugserver_launch_info, port_ptr, &args, -1);
 
   pid = debugserver_launch_info.GetProcessID();
+
+  if (error.Success()) {
+    LLDB_LOGF(log,
+              "GDBRemoteCommunicationServerPlatform::%s() "
+              "debugserver launched successfully as pid %" PRIu64,
+              __FUNCTION__, pid);
+  } else {
+    LLDB_LOGF(log,
+              "GDBRemoteCommunicationServerPlatform::%s() "
+              "debugserver launch failed: %s",
+              __FUNCTION__, error.AsCString());
+  }
+
+  // TODO: Be sure gdbserver uses the requested port.
+  // assert(!port_ptr || *port == 0 || *port == child_port)
+  // Use only the original *port returned by GetNextAvailablePort()
+  // for AssociatePortWithProcess() or FreePort() below.
+
   if (pid != LLDB_INVALID_PROCESS_ID) {
-    std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
-    m_spawned_pids.insert(pid);
+    AddSpawnedProcess(pid);
     if (*port > 0)
-      m_port_map.AssociatePortWithProcess(*port, pid);
+      g_port_map.AssociatePortWithProcess(*port, pid);
   } else {
     if (*port > 0)
-      m_port_map.FreePort(*port);
+      g_port_map.FreePort(*port);
   }
+  if (port_ptr)
+    *port = child_port;
   return error;
 }
 
@@ -230,10 +339,6 @@ GDBRemoteCommunicationServerPlatform::Handle_qLaunchGDBServer(
   // Spawn a local debugserver as a platform so we can then attach or launch a
   // process...
 
-  Log *log = GetLog(LLDBLog::Platform);
-  LLDB_LOGF(log, "GDBRemoteCommunicationServerPlatform::%s() called",
-            __FUNCTION__);
-
   ConnectionFileDescriptor file_conn;
   std::string hostname;
   packet.SetFilePos(::strlen("qLaunchGDBServer;"));
@@ -255,18 +360,9 @@ GDBRemoteCommunicationServerPlatform::Handle_qLaunchGDBServer(
   Status error =
       LaunchGDBServer(Args(), hostname, debugserver_pid, port, socket_name);
   if (error.Fail()) {
-    LLDB_LOGF(log,
-              "GDBRemoteCommunicationServerPlatform::%s() debugserver "
-              "launch failed: %s",
-              __FUNCTION__, error.AsCString());
     return SendErrorResponse(9);
   }
 
-  LLDB_LOGF(log,
-            "GDBRemoteCommunicationServerPlatform::%s() debugserver "
-            "launched successfully as pid %" PRIu64,
-            __FUNCTION__, debugserver_pid);
-
   StreamGDBRemote response;
   assert(port);
   response.Printf("pid:%" PRIu64 ";port:%u;", debugserver_pid,
@@ -317,28 +413,45 @@ GDBRemoteCommunicationServerPlatform::Handle_qKillSpawnedProcess(
 
   lldb::pid_t pid = packet.GetU64(LLDB_INVALID_PROCESS_ID);
 
+  if (SpawnedProcessFinished(pid))
+    m_spawned_pids.erase(pid);
+
   // verify that we know anything about this pid. Scope for locker
-  {
-    std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
-    if (m_spawned_pids.find(pid) == m_spawned_pids.end()) {
-      // not a pid we know about
-      return SendErrorResponse(10);
-    }
+  if ((m_spawned_pids.find(pid) == m_spawned_pids.end())) {
+    // not a pid we know about
+    return SendErrorResponse(10); // ECHILD
   }
 
   // go ahead and attempt to kill the spawned process
-  if (KillSpawnedProcess(pid))
+  if (KillSpawnedProcess(pid)) {
+    m_spawned_pids.erase(pid);
     return SendOKResponse();
-  else
-    return SendErrorResponse(11);
+  } else
+    return SendErrorResponse(11); // EDEADLK
+}
+
+void GDBRemoteCommunicationServerPlatform::AddSpawnedProcess(lldb::pid_t pid) {
+  std::lock_guard<std::mutex> guard(g_spawned_pids_mutex);
+
+  // If MonitorChildProcessThreadFunction() failed hope the system will not
+  // reuse pid of zombie processes.
+  // assert(g_spawned_pids.find(pid) == g_spawned_pids.end());
+
+  g_spawned_pids.insert(pid);
+  m_spawned_pids.insert(pid);
+}
+
+bool GDBRemoteCommunicationServerPlatform::SpawnedProcessFinished(
+    lldb::pid_t pid) {
+  std::lock_guard<std::mutex> guard(g_spawned_pids_mutex);
+  return (g_spawned_pids.find(pid) == g_spawned_pids.end());
 }
 
 bool GDBRemoteCommunicationServerPlatform::KillSpawnedProcess(lldb::pid_t pid) {
   // make sure we know about this process
-  {
-    std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
-    if (m_spawned_pids.find(pid) == m_spawned_pids.end())
-      return false;
+  if (SpawnedProcessFinished(pid)) {
+    // it seems the process has been finished recently
+    return true;
   }
 
   // first try a SIGTERM (standard kill)
@@ -346,46 +459,30 @@ bool GDBRemoteCommunicationServerPlatform::KillSpawnedProcess(lldb::pid_t pid) {
 
   // check if that worked
   for (size_t i = 0; i < 10; ++i) {
-    {
-      std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
-      if (m_spawned_pids.find(pid) == m_spawned_pids.end()) {
-        // it is now killed
-        return true;
-      }
+    if (SpawnedProcessFinished(pid)) {
+      // it is now killed
+      return true;
     }
     std::this_thread::sleep_for(std::chrono::milliseconds(10));
   }
 
-  {
-    std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
-    if (m_spawned_pids.find(pid) == m_spawned_pids.end())
-      return true;
-  }
+  if (SpawnedProcessFinished(pid))
+    return true;
 
   // the launched process still lives.  Now try killing it again, this time
   // with an unblockable signal.
   Host::Kill(pid, SIGKILL);
 
   for (size_t i = 0; i < 10; ++i) {
-    {
-      std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
-      if (m_spawned_pids.find(pid) == m_spawned_pids.end()) {
-        // it is now killed
-        return true;
-      }
+    if (SpawnedProcessFinished(pid)) {
+      // it is now killed
+      return true;
     }
     std::this_thread::sleep_for(std::chrono::milliseconds(10));
   }
 
   // check one more time after the final sleep
-  {
-    std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
-    if (m_spawned_pids.find(pid) == m_spawned_pids.end())
-      return true;
-  }
-
-  // no luck - the process still lives
-  return false;
+  return SpawnedProcessFinished(pid);
 }
 
 GDBRemoteCommunication::PacketResult
@@ -442,12 +539,14 @@ GDBRemoteCommunication::PacketResult
 GDBRemoteCommunicationServerPlatform::Handle_qGetWorkingDir(
     StringExtractorGDBRemote &packet) {
 
-  llvm::SmallString<64> cwd;
-  if (std::error_code ec = llvm::sys::fs::current_path(cwd))
-    return SendErrorResponse(ec.value());
+  auto cwd = FileSystem::Instance()
+                 .GetVirtualFileSystem()
+                 ->getCurrentWorkingDirectory();
+  if (!cwd)
+    return SendErrorResponse(cwd.getError());
 
   StreamString response;
-  response.PutBytesAsRawHex8(cwd.data(), cwd.size());
+  response.PutBytesAsRawHex8(cwd->data(), cwd->size());
   return SendPacketNoLock(response.GetString());
 }
 
@@ -458,7 +557,9 @@ GDBRemoteCommunicationServerPlatform::Handle_QSetWorkingDir(
   std::string path;
   packet.GetHexByteString(path);
 
-  if (std::error_code ec = llvm::sys::fs::set_current_path(path))
+  if (std::error_code ec = FileSystem::Instance()
+                               .GetVirtualFileSystem()
+                            ...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/100670


More information about the lldb-commits mailing list