https://github.com/da-viper updated 
https://github.com/llvm/llvm-project/pull/178083

>From 0d4eb594ea600e1cc2716f99e54906ddb6e72a42 Mon Sep 17 00:00:00 2001
From: Ebuka Ezike <[email protected]>
Date: Mon, 26 Jan 2026 21:28:48 +0000
Subject: [PATCH 1/2] [lldb] Fix memory monitor shutdown on Linux using eventfd

The current linux implementation has a 1 second timeout when polling
for memory pressure. lldb-dap may take up to an extra 1 second to
shutdown.
Use an event filedescriptor to immediately stop the memory monitor
thread.

Fixes #150220
---
 lldb/include/lldb/Host/MemoryMonitor.h    |  3 +-
 lldb/source/Host/common/MemoryMonitor.cpp | 98 ++++++++++++++++++-----
 2 files changed, 81 insertions(+), 20 deletions(-)

diff --git a/lldb/include/lldb/Host/MemoryMonitor.h 
b/lldb/include/lldb/Host/MemoryMonitor.h
index 504f5f9cba96b..541a647c2276f 100644
--- a/lldb/include/lldb/Host/MemoryMonitor.h
+++ b/lldb/include/lldb/Host/MemoryMonitor.h
@@ -11,6 +11,7 @@
 
 #include <functional>
 #include <memory>
+#include <utility>
 
 namespace lldb_private {
 
@@ -18,7 +19,7 @@ class MemoryMonitor {
 public:
   using Callback = std::function<void()>;
 
-  MemoryMonitor(Callback callback) : m_callback(callback) {}
+  MemoryMonitor(Callback callback) : m_callback(std::move(callback)) {}
   virtual ~MemoryMonitor() = default;
 
   /// MemoryMonitor is not copyable.
diff --git a/lldb/source/Host/common/MemoryMonitor.cpp 
b/lldb/source/Host/common/MemoryMonitor.cpp
index dbd44a4774758..d68f64e5c5043 100644
--- a/lldb/source/Host/common/MemoryMonitor.cpp
+++ b/lldb/source/Host/common/MemoryMonitor.cpp
@@ -13,7 +13,6 @@
 #include "lldb/Utility/Log.h"
 #include "llvm/ADT/ScopeExit.h"
 #include "llvm/Support/Error.h"
-#include <atomic>
 #include <cstddef>
 #include <cstdio>
 #include <cstring>
@@ -21,46 +20,102 @@
 #if defined(__linux__)
 #include <fcntl.h>
 #include <poll.h>
+#include <sys/eventfd.h>
+#include <sys/poll.h>
 #include <unistd.h>
 #endif
 
 #if defined(_WIN32)
+#include <atomic>
 #include <windows.h>
 #endif
 
 using namespace lldb_private;
 
-class MemoryMonitorPoll : public MemoryMonitor {
+#if defined(__linux__)
+class MemoryMonitorLinux : public MemoryMonitor {
 public:
   using MemoryMonitor::MemoryMonitor;
 
   lldb::thread_result_t MonitorThread() {
-#if defined(__linux__)
-    struct pollfd fds;
-    fds.fd = open("/proc/pressure/memory", O_RDWR | O_NONBLOCK);
-    if (fds.fd < 0)
+    constexpr size_t pressure_idx = 0;
+    constexpr size_t stop_idx = 1;
+    constexpr size_t fd_count = 2;
+    std::array<pollfd, fd_count> pfds{};
+
+    // Setup stop file descriptor.
+    m_stop_fd = ::eventfd(0, O_NONBLOCK);
+    if (m_stop_fd < 0)
+      return {};
+    pfds[stop_idx].fd = m_stop_fd;
+    pfds[stop_idx].events = POLLIN;
+
+    // Setup pressure file descriptor.
+    pfds[pressure_idx].fd =
+        ::open("/proc/pressure/memory", O_RDWR | O_NONBLOCK);
+    if (pfds[pressure_idx].fd < 0) {
+      ::close(m_stop_fd);
       return {};
-    fds.events = POLLPRI;
+    }
+    pfds[pressure_idx].events = POLLPRI;
 
-    llvm::scope_exit cleanup([&]() { close(fds.fd); });
+    llvm::scope_exit cleanup([&]() {
+      ::close(pfds[pressure_idx].fd);
+      ::close(m_stop_fd);
+    });
 
     // Detect a 50ms stall in a 2 second time window.
-    const char trig[] = "some 50000 2000000";
-    if (write(fds.fd, trig, strlen(trig) + 1) < 0)
+    constexpr llvm::StringRef trigger = "some 50000 2000000";
+    if (::write(pfds[pressure_idx].fd, trigger.data(), trigger.size()) < 0)
       return {};
 
-    while (!m_done) {
-      int n = poll(&fds, 1, g_timeout);
+    while (true) {
+      constexpr int timeout_infinite = -1;
+      const int n = ::poll(pfds.data(), pfds.size(), timeout_infinite);
       if (n > 0) {
-        if (fds.revents & POLLERR)
+        // Handle stop event.
+        if (pfds[stop_idx].revents & (POLLIN | POLLERR))
+          return {};
+
+        if (pfds[pressure_idx].revents & POLLERR)
           return {};
-        if (fds.revents & POLLPRI)
+        if (pfds[pressure_idx].revents & POLLPRI)
           m_callback();
       }
     }
-#endif
+    return {};
+  }
 
-#if defined(_WIN32)
+  void Start() override {
+    llvm::Expected<HostThread> memory_monitor_thread =
+        ThreadLauncher::LaunchThread("memory.monitor",
+                                     [this] { return MonitorThread(); });
+    if (memory_monitor_thread) {
+      m_memory_monitor_thread = *memory_monitor_thread;
+    } else {
+      LLDB_LOG_ERROR(GetLog(LLDBLog::Host), memory_monitor_thread.takeError(),
+                     "failed to launch host thread: {0}");
+    }
+  }
+
+  void Stop() override {
+    if (m_memory_monitor_thread.IsJoinable()) {
+      ::eventfd_write(m_stop_fd, 1);
+      m_memory_monitor_thread.Join(nullptr);
+    }
+  }
+
+private:
+  int m_stop_fd = -1;
+  HostThread m_memory_monitor_thread;
+};
+#elif defined(_WIN32)
+
+class MemoryMonitorWindows : public MemoryMonitor {
+public:
+  using MemoryMonitor::MemoryMonitor;
+
+  lldb::thread_result_t MonitorThread() {
     HANDLE low_memory_notification =
         CreateMemoryResourceNotification(LowMemoryResourceNotification);
     if (!low_memory_notification)
@@ -72,8 +127,6 @@ class MemoryMonitorPoll : public MemoryMonitor {
         m_callback();
       }
     }
-#endif
-
     return {};
   }
 
@@ -101,9 +154,16 @@ class MemoryMonitorPoll : public MemoryMonitor {
   std::atomic<bool> m_done = false;
   HostThread m_memory_monitor_thread;
 };
+#endif
 
 #if !defined(__APPLE__)
 std::unique_ptr<MemoryMonitor> MemoryMonitor::Create(Callback callback) {
-  return std::make_unique<MemoryMonitorPoll>(callback);
+#if defined(__linux__)
+  return std::make_unique<MemoryMonitorLinux>(std::move(callback));
+#elif defined(_WIN32)
+  return std::make_unique<MemoryMonitorWindows>(std::move(callback));
+#else
+  return nullptr;
+#endif
 }
 #endif

>From 12d9fe14df288a8e8646d31f827463a8b581fe04 Mon Sep 17 00:00:00 2001
From: Ebuka Ezike <[email protected]>
Date: Tue, 27 Jan 2026 20:04:35 +0000
Subject: [PATCH 2/2] make the monitor thread private

---
 lldb/source/Host/common/MemoryMonitor.cpp | 73 +++++++++++++----------
 1 file changed, 42 insertions(+), 31 deletions(-)

diff --git a/lldb/source/Host/common/MemoryMonitor.cpp 
b/lldb/source/Host/common/MemoryMonitor.cpp
index d68f64e5c5043..fc873b6bd9e50 100644
--- a/lldb/source/Host/common/MemoryMonitor.cpp
+++ b/lldb/source/Host/common/MemoryMonitor.cpp
@@ -37,6 +37,46 @@ class MemoryMonitorLinux : public MemoryMonitor {
 public:
   using MemoryMonitor::MemoryMonitor;
 
+  explicit MemoryMonitorLinux(Callback callback)
+      : MemoryMonitor(std::move(callback)),
+        m_stop_fd(::eventfd(0, EFD_NONBLOCK)) {}
+
+  ~MemoryMonitorLinux() {
+    if (m_memory_monitor_thread.IsJoinable())
+      m_memory_monitor_thread.Join(nullptr);
+    if (m_stop_fd != 1)
+      ::close(m_stop_fd);
+  }
+
+  void Start() override {
+    if (m_stop_fd < 0) {
+      LLDB_LOG_ERROR(
+          GetLog(LLDBLog::Host),
+          llvm::errorCodeToError(llvm::errnoAsErrorCode()),
+          "failed to create stop file descriptor for memory monitor: {0}");
+      return;
+    }
+
+    llvm::Expected<HostThread> memory_monitor_thread =
+        ThreadLauncher::LaunchThread("memory.monitor",
+                                     [this] { return MonitorThread(); });
+    if (memory_monitor_thread) {
+      m_memory_monitor_thread = *memory_monitor_thread;
+    } else {
+      LLDB_LOG_ERROR(GetLog(LLDBLog::Host), memory_monitor_thread.takeError(),
+                     "failed to launch host thread: {0}");
+    }
+  }
+
+  void Stop() override {
+    if (m_memory_monitor_thread.IsJoinable()) {
+      if (m_stop_fd != -1)
+        ::eventfd_write(m_stop_fd, 1);
+      m_memory_monitor_thread.Join(nullptr);
+    }
+  }
+
+private:
   lldb::thread_result_t MonitorThread() {
     constexpr size_t pressure_idx = 0;
     constexpr size_t stop_idx = 1;
@@ -44,25 +84,17 @@ class MemoryMonitorLinux : public MemoryMonitor {
     std::array<pollfd, fd_count> pfds{};
 
     // Setup stop file descriptor.
-    m_stop_fd = ::eventfd(0, O_NONBLOCK);
-    if (m_stop_fd < 0)
-      return {};
     pfds[stop_idx].fd = m_stop_fd;
     pfds[stop_idx].events = POLLIN;
 
     // Setup pressure file descriptor.
     pfds[pressure_idx].fd =
         ::open("/proc/pressure/memory", O_RDWR | O_NONBLOCK);
-    if (pfds[pressure_idx].fd < 0) {
-      ::close(m_stop_fd);
+    if (pfds[pressure_idx].fd < 0)
       return {};
-    }
     pfds[pressure_idx].events = POLLPRI;
 
-    llvm::scope_exit cleanup([&]() {
-      ::close(pfds[pressure_idx].fd);
-      ::close(m_stop_fd);
-    });
+    llvm::scope_exit cleanup([&]() { ::close(pfds[pressure_idx].fd); });
 
     // Detect a 50ms stall in a 2 second time window.
     constexpr llvm::StringRef trigger = "some 50000 2000000";
@@ -85,27 +117,6 @@ class MemoryMonitorLinux : public MemoryMonitor {
     }
     return {};
   }
-
-  void Start() override {
-    llvm::Expected<HostThread> memory_monitor_thread =
-        ThreadLauncher::LaunchThread("memory.monitor",
-                                     [this] { return MonitorThread(); });
-    if (memory_monitor_thread) {
-      m_memory_monitor_thread = *memory_monitor_thread;
-    } else {
-      LLDB_LOG_ERROR(GetLog(LLDBLog::Host), memory_monitor_thread.takeError(),
-                     "failed to launch host thread: {0}");
-    }
-  }
-
-  void Stop() override {
-    if (m_memory_monitor_thread.IsJoinable()) {
-      ::eventfd_write(m_stop_fd, 1);
-      m_memory_monitor_thread.Join(nullptr);
-    }
-  }
-
-private:
   int m_stop_fd = -1;
   HostThread m_memory_monitor_thread;
 };

_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to