From 0fac3a49e9c79821232743839ee07845d7d50675 Mon Sep 17 00:00:00 2001 From: Shweta Khatri Date: Thu, 12 Feb 2026 17:30:46 -0500 Subject: [PATCH 1/3] rocr: IPC: Manage IPC socket thread lifetime Track IPC socket server thread handle Join/close thread during runtime unload to clear ASan-reported leaks --- .../runtime/hsa-runtime/core/inc/runtime.h | 1 + .../runtime/hsa-runtime/core/runtime/runtime.cpp | 12 +++++++++--- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/projects/rocr-runtime/runtime/hsa-runtime/core/inc/runtime.h b/projects/rocr-runtime/runtime/hsa-runtime/core/inc/runtime.h index b8f2dc5160a..91adc1d5f14 100644 --- a/projects/rocr-runtime/runtime/hsa-runtime/core/inc/runtime.h +++ b/projects/rocr-runtime/runtime/hsa-runtime/core/inc/runtime.h @@ -906,6 +906,7 @@ class Runtime { int ipc_sock_server_fd_; std::map ipc_sock_server_conns_; std::mutex ipc_sock_server_lock_; + os::Thread ipc_sock_server_thread_; lazy_ptr asyncSignals_; lazy_ptr asyncExceptions_; diff --git a/projects/rocr-runtime/runtime/hsa-runtime/core/runtime/runtime.cpp b/projects/rocr-runtime/runtime/hsa-runtime/core/runtime/runtime.cpp index ad30d00c96e..617f85b4036 100644 --- a/projects/rocr-runtime/runtime/hsa-runtime/core/runtime/runtime.cpp +++ b/projects/rocr-runtime/runtime/hsa-runtime/core/runtime/runtime.cpp @@ -1461,7 +1461,7 @@ hsa_status_t Runtime::IPCCreate(void* ptr, size_t len, hsa_amd_ipc_memory_t* han // Spin server client acceptance into a socket server thread. // Socket server needs to last for the lifetime of the runtime instance // as the attach life cycle is unknown. - os::CreateThread(AsyncIPCSockServerConnLoop, NULL); + ipc_sock_server_thread_ = os::CreateThread(AsyncIPCSockServerConnLoop, NULL); } #else assert(!"Unimplemented! Do we really need this?"); @@ -2358,8 +2358,8 @@ Runtime::Runtime() internal_queue_create_notifier_user_data_(nullptr), ref_count_(0), kfd_version{}, - ipc_sock_server_fd_(0) { - + ipc_sock_server_fd_(0), + ipc_sock_server_thread_(nullptr) { virtual_mem_api_supported_ = false; ipc_dmabuf_supported_ = false; xnack_enabled_ = false; @@ -2449,6 +2449,12 @@ void Runtime::Unload() { IPCClientImport(getpid(), IPC_SOCK_SERVER_CONN_CLOSE_HANDLE, 0, nullptr, nullptr, nullptr, false, 0); + if (ipc_sock_server_thread_) { + os::WaitForThread(ipc_sock_server_thread_); + os::CloseThread(ipc_sock_server_thread_); + ipc_sock_server_thread_ = nullptr; + } + svm_profile_.reset(nullptr); UnloadTools(); From 356a60c69fb6e845f4bae911b7200823fe43788e Mon Sep 17 00:00:00 2001 From: Shweta Khatri Date: Mon, 16 Feb 2026 09:29:32 -0500 Subject: [PATCH 2/3] rocr: IPC: Handle IPC socket server thread errors and cleanup before restart --- .../runtime/hsa-runtime/core/runtime/runtime.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/projects/rocr-runtime/runtime/hsa-runtime/core/runtime/runtime.cpp b/projects/rocr-runtime/runtime/hsa-runtime/core/runtime/runtime.cpp index 617f85b4036..5a5e6792bd4 100644 --- a/projects/rocr-runtime/runtime/hsa-runtime/core/runtime/runtime.cpp +++ b/projects/rocr-runtime/runtime/hsa-runtime/core/runtime/runtime.cpp @@ -1434,6 +1434,13 @@ hsa_status_t Runtime::IPCCreate(void* ptr, size_t len, hsa_amd_ipc_memory_t* han std::lock_guard lock(ipc_sock_server_lock_); #if defined(__linux__) if (!ipc_sock_server_conns_.size()) { // create new runtime socket server + // Ensure any previous IPC server thread handle is released before starting a new one. + if (ipc_sock_server_thread_) { + os::WaitForThread(ipc_sock_server_thread_); + os::CloseThread(ipc_sock_server_thread_); + ipc_sock_server_thread_ = nullptr; + } + struct sockaddr_un address; ipc_sock_server_fd_ = socket(AF_UNIX, SOCK_STREAM, 0); assert(ipc_sock_server_fd_ > -1 && "DMA buffer could not be exported for IPC!"); @@ -1462,6 +1469,11 @@ hsa_status_t Runtime::IPCCreate(void* ptr, size_t len, hsa_amd_ipc_memory_t* han // Socket server needs to last for the lifetime of the runtime instance // as the attach life cycle is unknown. ipc_sock_server_thread_ = os::CreateThread(AsyncIPCSockServerConnLoop, NULL); + if (!ipc_sock_server_thread_) { + close(ipc_sock_server_fd_); + ipc_sock_server_fd_ = -1; + return HSA_STATUS_ERROR; + } } #else assert(!"Unimplemented! Do we really need this?"); From 94f67e3dc980f22496d31433b8787dc879cad307 Mon Sep 17 00:00:00 2001 From: Shweta Khatri Date: Thu, 19 Feb 2026 23:23:27 -0500 Subject: [PATCH 3/3] rocr: IPC: close IPC socket fd on bind/listen failure and clear conns on thread failure The bind() and listen() error paths returned without closing the socket fd and leaking it. Thread-creation failure also left stale entries in ipc_sock_server_conns_. Clean up properly in all three cases. --- .../runtime/hsa-runtime/core/runtime/runtime.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/projects/rocr-runtime/runtime/hsa-runtime/core/runtime/runtime.cpp b/projects/rocr-runtime/runtime/hsa-runtime/core/runtime/runtime.cpp index 5a5e6792bd4..7e2572383e9 100644 --- a/projects/rocr-runtime/runtime/hsa-runtime/core/runtime/runtime.cpp +++ b/projects/rocr-runtime/runtime/hsa-runtime/core/runtime/runtime.cpp @@ -1460,16 +1460,25 @@ hsa_status_t Runtime::IPCCreate(void* ptr, size_t len, hsa_amd_ipc_memory_t* han address.sun_path[0] = 0; // first NULL char creates unlisted abstract socket int err = bind(ipc_sock_server_fd_, (struct sockaddr *)&address, sizeof(struct sockaddr_un)); assert(!err && "Connection to export DMA buffer not made!"); - if (err) return HSA_STATUS_ERROR; + if (err) { + close(ipc_sock_server_fd_); + ipc_sock_server_fd_ = -1; + return HSA_STATUS_ERROR; + } err = listen(ipc_sock_server_fd_, 1); assert(!err && "Connection to export DMA buffer not made!"); - if (err) return HSA_STATUS_ERROR; + if (err) { + close(ipc_sock_server_fd_); + ipc_sock_server_fd_ = -1; + return HSA_STATUS_ERROR; + } // Spin server client acceptance into a socket server thread. // Socket server needs to last for the lifetime of the runtime instance // as the attach life cycle is unknown. ipc_sock_server_thread_ = os::CreateThread(AsyncIPCSockServerConnLoop, NULL); if (!ipc_sock_server_thread_) { + ipc_sock_server_conns_.clear(); close(ipc_sock_server_fd_); ipc_sock_server_fd_ = -1; return HSA_STATUS_ERROR;