Enable leak backtraces by setting LEAK_BACKTRACE=1
Co-Authored-By: Nathan Sobo <nathan@zed.dev>
This commit is contained in:
parent
4cfd345f9d
commit
aa03ebce0e
1 changed files with 24 additions and 5 deletions
|
@ -10,6 +10,7 @@ use crate::{
|
||||||
use anyhow::{anyhow, Result};
|
use anyhow::{anyhow, Result};
|
||||||
use backtrace::Backtrace;
|
use backtrace::Backtrace;
|
||||||
use keymap::MatchResult;
|
use keymap::MatchResult;
|
||||||
|
use lazy_static::lazy_static;
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use platform::Event;
|
use platform::Event;
|
||||||
use postage::{mpsc, oneshot, sink::Sink as _, stream::Stream as _};
|
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)]
|
#[derive(Default)]
|
||||||
pub struct LeakDetector {
|
pub struct LeakDetector {
|
||||||
next_handle_id: usize,
|
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 {
|
impl LeakDetector {
|
||||||
fn handle_created(&mut self, type_name: Option<&'static str>, entity_id: usize) -> usize {
|
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 handle_id = post_inc(&mut self.next_handle_id);
|
||||||
let entry = self.handle_backtraces.entry(entity_id).or_default();
|
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 {
|
if let Some(type_name) = type_name {
|
||||||
entry.0.get_or_insert(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
|
handle_id
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3803,12 +3814,20 @@ impl LeakDetector {
|
||||||
id
|
id
|
||||||
);
|
);
|
||||||
for trace in backtraces.values_mut() {
|
for trace in backtraces.values_mut() {
|
||||||
trace.resolve();
|
if let Some(trace) = trace {
|
||||||
eprintln!("{:?}", CwdBacktrace(trace));
|
trace.resolve();
|
||||||
|
eprintln!("{:?}", CwdBacktrace(trace));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
found_leaks = true;
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue