[llvm] [Support] Fix memory leak in `Timer.cpp` on shutdown (PR #159983)

Alexandre Ganea via llvm-commits llvm-commits at lists.llvm.org
Sun Sep 21 12:52:09 PDT 2025


https://github.com/aganea updated https://github.com/llvm/llvm-project/pull/159983

>From 5d7d09a118014a6efd008a26a6dda8eedc4f1733 Mon Sep 17 00:00:00 2001
From: Alexandre Ganea <alex_toresh at yahoo.fr>
Date: Sun, 21 Sep 2025 11:07:20 -0400
Subject: [PATCH 1/2] [Support] Fix memory leak in Timer on shutdown

---
 llvm/lib/Support/Timer.cpp | 23 +++++++++++++++++++----
 1 file changed, 19 insertions(+), 4 deletions(-)

diff --git a/llvm/lib/Support/Timer.cpp b/llvm/lib/Support/Timer.cpp
index 75ec299a98376..20f51afe4ee74 100644
--- a/llvm/lib/Support/Timer.cpp
+++ b/llvm/lib/Support/Timer.cpp
@@ -57,6 +57,7 @@ static SignpostEmitter &signposts();
 static sys::SmartMutex<true> &timerLock();
 static TimerGroup &defaultTimerGroup();
 static Name2PairMap &namedGroupedTimers();
+static bool isTimerGlobalsConstructed();
 
 //===----------------------------------------------------------------------===//
 //
@@ -305,14 +306,24 @@ TimerGroup::~TimerGroup() {
     PrintQueuedTimers(*OutStream);
   }
 
+  auto unlink = [&]() {
+    *Prev = Next;
+    if (Next)
+      Next->Prev = Prev;
+  };
+
+  // If the managed instance is already dead, it means we're in the CRT
+  // destruction, so no need to lock.
+  if (!isTimerGlobalsConstructed()) {
+    unlink();
+    return;
+  }
+
   // Remove the group from the TimerGroupList.
   sys::SmartScopedLock<true> L(timerLock());
-  *Prev = Next;
-  if (Next)
-    Next->Prev = Prev;
+  unlink();
 }
 
-
 void TimerGroup::removeTimer(Timer &T) {
   sys::SmartScopedLock<true> L(timerLock());
 
@@ -557,3 +568,7 @@ void TimerGroup::constructForStatistics() {
 }
 
 void *TimerGroup::acquireTimerGlobals() { return ManagedTimerGlobals.claim(); }
+
+static bool isTimerGlobalsConstructed() {
+  return ManagedTimerGlobals.isConstructed();
+}

>From 5c0e7c9ebe1b4e54298f74a6e092819ee1e56baa Mon Sep 17 00:00:00 2001
From: Alexandre Ganea <alex_toresh at yahoo.fr>
Date: Sun, 21 Sep 2025 15:51:45 -0400
Subject: [PATCH 2/2] Clarify comment.

---
 llvm/lib/Support/Timer.cpp | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/llvm/lib/Support/Timer.cpp b/llvm/lib/Support/Timer.cpp
index 20f51afe4ee74..67483ba9dd655 100644
--- a/llvm/lib/Support/Timer.cpp
+++ b/llvm/lib/Support/Timer.cpp
@@ -312,8 +312,10 @@ TimerGroup::~TimerGroup() {
       Next->Prev = Prev;
   };
 
-  // If the managed instance is already dead, it means we're in the CRT
-  // destruction, so no need to lock.
+  // TimerGlobals is always created implicity, through a call to timerLock(),
+  // when a TimeGroup is created. On CRT shutdown, the TimerGlobals instance
+  // might have been destroyed already. Avoid re-creating it if calling
+  // timerLock().
   if (!isTimerGlobalsConstructed()) {
     unlink();
     return;



More information about the llvm-commits mailing list