From bddb8f14d18ccc159b958b8fb50684efe7e17893 Mon Sep 17 00:00:00 2001 From: "Andryeyev, German" Date: Wed, 14 May 2025 11:51:26 -0400 Subject: [PATCH] SWDEV-345024 - Retain the program on Fini kernel execution (#307) Fini kernel is executed during the invocation of amd::Program destructor, but the dispatch logic can retain/release the reference counter and cause double free. Avoid double free with an extra retain() call --- rocclr/platform/runtime.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/rocclr/platform/runtime.cpp b/rocclr/platform/runtime.cpp index c170b11259..6a238b1e77 100644 --- a/rocclr/platform/runtime.cpp +++ b/rocclr/platform/runtime.cpp @@ -127,13 +127,20 @@ void RuntimeTearDown::RegisterObject(ReferenceCountedObject* obj) { class RuntimeTearDown runtime_tear_down; uint ReferenceCountedObject::retain() { - return referenceCount_.fetch_add(1, std::memory_order_relaxed) + 1; + uint prev = referenceCount_.fetch_add(1, std::memory_order_relaxed); + assert(prev != 0 && "An object with count==0 is invalid"); + return prev + 1; } uint ReferenceCountedObject::release() { uint newCount = referenceCount_.fetch_sub(1, std::memory_order_relaxed) - 1; if (newCount == 0) { if (terminate()) { + // The destructor should be called with a count==1 for the last thread + // releasing the reference. Since an atomic load before the decrement + // would add more atomic operations, simply bump the count to 1 here + // before destructing the object. + referenceCount_.store(1, std::memory_order_relaxed); delete this; } }