Prechádzať zdrojové kódy

Merge pull request #1580 from ealmloff/miri-leak

Remove the ignore leaks in flag MIRI
Jonathan Kelley 1 rok pred
rodič
commit
07d84fedb7

+ 1 - 2
.github/workflows/miri.yml

@@ -86,8 +86,7 @@ jobs:
 
         # working-directory: tokio
         env:
-          #  todo: disable memory leaks ignore
-          MIRIFLAGS: -Zmiri-disable-isolation -Zmiri-strict-provenance -Zmiri-retag-fields -Zmiri-ignore-leaks
+          MIRIFLAGS: -Zmiri-disable-isolation -Zmiri-strict-provenance -Zmiri-retag-fields
           PROPTEST_CASES: 10
 
       # Cache the global cargo directory, but NOT the local `target` directory which

+ 20 - 1
packages/core/src/bump_frame.rs

@@ -1,5 +1,5 @@
 use crate::nodes::RenderReturn;
-use crate::{Attribute, AttributeValue};
+use crate::{Attribute, AttributeValue, VComponent};
 use bumpalo::Bump;
 use std::cell::RefCell;
 use std::cell::{Cell, UnsafeCell};
@@ -7,7 +7,10 @@ use std::cell::{Cell, UnsafeCell};
 pub(crate) struct BumpFrame {
     pub bump: UnsafeCell<Bump>,
     pub node: Cell<*const RenderReturn<'static>>,
+
+    // The bump allocator will not call the destructor of the objects it allocated. Attributes and props need to have there destructor called, so we keep a list of them to drop before the bump allocator is reset.
     pub(crate) attributes_to_drop_before_reset: RefCell<Vec<*const Attribute<'static>>>,
+    pub(crate) props_to_drop_before_reset: RefCell<Vec<*const VComponent<'static>>>,
 }
 
 impl BumpFrame {
@@ -17,6 +20,7 @@ impl BumpFrame {
             bump: UnsafeCell::new(bump),
             node: Cell::new(std::ptr::null()),
             attributes_to_drop_before_reset: Default::default(),
+            props_to_drop_before_reset: Default::default(),
         }
     }
 
@@ -41,6 +45,10 @@ impl BumpFrame {
             .push(attribute);
     }
 
+    /// Reset the bump allocator and drop all the attributes and props that were allocated in it.
+    ///
+    /// # Safety
+    /// The caller must insure that no reference to anything allocated in the bump allocator is available after this function is called.
     pub(crate) unsafe fn reset(&self) {
         let mut attributes = self.attributes_to_drop_before_reset.borrow_mut();
         attributes.drain(..).for_each(|attribute| {
@@ -49,9 +57,20 @@ impl BumpFrame {
                 _ = l.take();
             }
         });
+        let mut props = self.props_to_drop_before_reset.borrow_mut();
+        props.drain(..).for_each(|prop| {
+            let prop = unsafe { &*prop };
+            _ = prop.props.borrow_mut().take();
+        });
         unsafe {
             let bump = &mut *self.bump.get();
             bump.reset();
         }
     }
 }
+
+impl Drop for BumpFrame {
+    fn drop(&mut self) {
+        unsafe { self.reset() }
+    }
+}

+ 6 - 1
packages/core/src/scopes.rs

@@ -367,12 +367,17 @@ impl<'src> ScopeState {
         }
 
         let mut props = self.borrowed_props.borrow_mut();
+        let mut drop_props = self
+            .previous_frame()
+            .props_to_drop_before_reset
+            .borrow_mut();
         for node in element.dynamic_nodes {
             if let DynamicNode::Component(comp) = node {
+                let unbounded = unsafe { std::mem::transmute(comp as *const VComponent) };
                 if !comp.static_props {
-                    let unbounded = unsafe { std::mem::transmute(comp as *const VComponent) };
                     props.push(unbounded);
                 }
+                drop_props.push(unbounded);
             }
         }