Enable leak backtraces by setting `LEAK_BACKTRACE=1`

Antonio Scandurra and Nathan Sobo created

Co-Authored-By: Nathan Sobo <nathan@zed.dev>

Change summary

crates/gpui/src/app.rs | 29 ++++++++++++++++++++++++-----
1 file changed, 24 insertions(+), 5 deletions(-)

Detailed changes

crates/gpui/src/app.rs 🔗

@@ -10,6 +10,7 @@ use crate::{
 use anyhow::{anyhow, Result};
 use backtrace::Backtrace;
 use keymap::MatchResult;
+use lazy_static::lazy_static;
 use parking_lot::Mutex;
 use platform::Event;
 use postage::{mpsc, oneshot, sink::Sink as _, stream::Stream as _};
@@ -3767,20 +3768,30 @@ impl Drop for Subscription {
     }
 }
 
+lazy_static! {
+    static ref LEAK_BACKTRACE: bool =
+        std::env::var("LEAK_BACKTRACE").map_or(false, |b| !b.is_empty());
+}
+
 #[derive(Default)]
 pub struct LeakDetector {
     next_handle_id: usize,
-    handle_backtraces: HashMap<usize, (Option<&'static str>, HashMap<usize, Backtrace>)>,
+    handle_backtraces: HashMap<usize, (Option<&'static str>, HashMap<usize, Option<Backtrace>>)>,
 }
 
 impl LeakDetector {
     fn handle_created(&mut self, type_name: Option<&'static str>, entity_id: usize) -> usize {
         let handle_id = post_inc(&mut self.next_handle_id);
         let entry = self.handle_backtraces.entry(entity_id).or_default();
+        let backtrace = if *LEAK_BACKTRACE {
+            Some(Backtrace::new_unresolved())
+        } else {
+            None
+        };
         if let Some(type_name) = type_name {
             entry.0.get_or_insert(type_name);
         }
-        entry.1.insert(handle_id, Backtrace::new_unresolved());
+        entry.1.insert(handle_id, backtrace);
         handle_id
     }
 
@@ -3803,12 +3814,20 @@ impl LeakDetector {
                 id
             );
             for trace in backtraces.values_mut() {
-                trace.resolve();
-                eprintln!("{:?}", CwdBacktrace(trace));
+                if let Some(trace) = trace {
+                    trace.resolve();
+                    eprintln!("{:?}", CwdBacktrace(trace));
+                }
             }
             found_leaks = true;
         }
-        assert!(!found_leaks, "detected leaked handles");
+
+        let hint = if *LEAK_BACKTRACE {
+            ""
+        } else {
+            " – set LEAK_BACKTRACE=1 for more information"
+        };
+        assert!(!found_leaks, "detected leaked handles{}", hint);
     }
 }