[llvm-branch-commits] [lldb] release/22.x: [lldb] Fix memory monitor shutdown on Linux using eventfd (#178083) (PR #179199)
via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Mon Feb 2 02:26:13 PST 2026
https://github.com/llvmbot created https://github.com/llvm/llvm-project/pull/179199
Backport a5ffce0faebe5f49d8befb774f4cb781b9e33df7
Requested by: @da-viper
>From b0c932865560214cc0f77cf6b2171d30bf41c41a Mon Sep 17 00:00:00 2001
From: Ebuka Ezike <yerimyah1 at gmail.com>
Date: Thu, 29 Jan 2026 10:01:17 +0000
Subject: [PATCH] [lldb] Fix memory monitor shutdown on Linux using eventfd
(#178083)
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 file descriptor to immediately stop the memory monitor
thread.
Fixes #150220
(cherry picked from commit a5ffce0faebe5f49d8befb774f4cb781b9e33df7)
---
lldb/include/lldb/Host/MemoryMonitor.h | 3 +-
lldb/source/Host/common/MemoryMonitor.cpp | 109 ++++++++++++++++++----
2 files changed, 92 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..7734be8688675 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,113 @@
#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;
+ 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() {
-#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.
+ 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)
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); });
// 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() + 1) < 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 (fds.revents & POLLPRI)
+
+ if (pfds[pressure_idx].revents & POLLERR)
+ return {};
+ if (pfds[pressure_idx].revents & POLLPRI)
m_callback();
}
}
-#endif
+ return {};
+ }
+ int m_stop_fd = -1;
+ HostThread m_memory_monitor_thread;
+};
+#elif defined(_WIN32)
-#if 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 +138,6 @@ class MemoryMonitorPoll : public MemoryMonitor {
m_callback();
}
}
-#endif
-
return {};
}
@@ -101,9 +165,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
More information about the llvm-branch-commits
mailing list