Fix memory leak in owner (#2245)

* Fix: memory leak on listeners for elements

---------

Co-authored-by: Evan Almloff <evanalmloff@gmail.com>
This commit is contained in:
Jonathan Kelley 2024-04-04 15:32:23 -07:00 committed by GitHub
parent 44fe2defc2
commit 633e2a70a4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 16 additions and 6 deletions

View file

@ -1,6 +1,5 @@
use generational_box::{GenerationalBox, UnsyncStorage}; use crate::{global_context::current_scope_id, Runtime, ScopeId};
use generational_box::GenerationalBox;
use crate::{generational_box::current_owner, global_context::current_scope_id, Runtime, ScopeId};
use std::{cell::Cell, rc::Rc}; use std::{cell::Cell, rc::Rc};
/// A wrapper around some generic data that handles the event's state /// A wrapper around some generic data that handles the event's state
@ -199,8 +198,7 @@ impl<T: 'static> EventHandler<T> {
/// Create a new [`EventHandler`] from an [`FnMut`] /// Create a new [`EventHandler`] from an [`FnMut`]
#[track_caller] #[track_caller]
pub fn new(mut f: impl FnMut(T) + 'static) -> EventHandler<T> { pub fn new(mut f: impl FnMut(T) + 'static) -> EventHandler<T> {
let owner = current_owner::<UnsyncStorage>(); let callback = GenerationalBox::leak(Some(Box::new(move |event: T| {
let callback = owner.insert(Some(Box::new(move |event: T| {
f(event); f(event);
}) as Box<dyn FnMut(T)>)); }) as Box<dyn FnMut(T)>));
EventHandler { EventHandler {

View file

@ -70,7 +70,7 @@ core-foundation = "0.9.3"
objc = "0.2.7" objc = "0.2.7"
[features] [features]
default = ["tokio_runtime", "wry/objc-exception", "hot-reload"] default = ["tokio_runtime", "wry/objc-exception", "hot-reload", "devtools"]
tokio_runtime = ["tokio"] tokio_runtime = ["tokio"]
fullscreen = ["wry/fullscreen"] fullscreen = ["wry/fullscreen"]
transparent = ["wry/transparent"] transparent = ["wry/transparent"]

View file

@ -66,6 +66,18 @@ impl<T, S: AnyStorage> Debug for GenerationalBox<T, S> {
} }
impl<T, S: Storage<T>> GenerationalBox<T, S> { impl<T, S: Storage<T>> GenerationalBox<T, S> {
/// Create a new generational box by leaking a value into the storage. This is useful for creating
/// a box that needs to be manually dropped with no owners.
#[track_caller]
pub fn leak(value: T) -> Self {
let mut location = S::claim();
location.replace_with_caller(
value,
#[cfg(any(debug_assertions, feature = "debug_ownership"))]
std::panic::Location::caller(),
)
}
#[inline(always)] #[inline(always)]
pub(crate) fn validate(&self) -> bool { pub(crate) fn validate(&self) -> bool {
#[cfg(any(debug_assertions, feature = "check_generation"))] #[cfg(any(debug_assertions, feature = "check_generation"))]