Skip to content

Commit 3cf10e2

Browse files
committed
prevent memory leak when dropping ParallelSystemContainer (#2176)
`ParallelSystemContainer`'s `system` pointer was extracted from box, but it was never deallocated. This change adds missing drop implementation that cleans up that memory.
1 parent 1d65294 commit 3cf10e2

File tree

1 file changed

+8
-8
lines changed

1 file changed

+8
-8
lines changed

crates/bevy_ecs/src/schedule/system_container.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use crate::{
77
},
88
system::{ExclusiveSystem, System},
99
};
10-
use std::{borrow::Cow, ptr::NonNull};
10+
use std::{borrow::Cow, cell::UnsafeCell};
1111

1212
/// System metadata like its name, labels, order requirements and component access.
1313
pub trait SystemContainer: GraphNode<Label = BoxedSystemLabel> {
@@ -106,7 +106,7 @@ impl SystemContainer for ExclusiveSystemContainer {
106106
}
107107

108108
pub struct ParallelSystemContainer {
109-
system: NonNull<dyn System<In = (), Out = ()>>,
109+
system: Box<UnsafeCell<dyn System<In = (), Out = ()>>>,
110110
pub(crate) run_criteria_index: Option<usize>,
111111
pub(crate) run_criteria_label: Option<BoxedRunCriteriaLabel>,
112112
pub(crate) should_run: bool,
@@ -123,7 +123,8 @@ unsafe impl Sync for ParallelSystemContainer {}
123123
impl ParallelSystemContainer {
124124
pub(crate) fn from_descriptor(descriptor: ParallelSystemDescriptor) -> Self {
125125
ParallelSystemContainer {
126-
system: unsafe { NonNull::new_unchecked(Box::into_raw(descriptor.system)) },
126+
// SAFE: it is fine to wrap inner value with UnsafeCell, as it is repr(transparent)
127+
system: unsafe { Box::from_raw(Box::into_raw(descriptor.system) as *mut _) },
127128
should_run: false,
128129
run_criteria_index: None,
129130
run_criteria_label: None,
@@ -140,20 +141,19 @@ impl ParallelSystemContainer {
140141
}
141142

142143
pub fn system(&self) -> &dyn System<In = (), Out = ()> {
143-
// SAFE: statically enforced shared access.
144-
unsafe { self.system.as_ref() }
144+
// SAFE: statically enforced shared access
145+
unsafe { self.system.get().as_ref().unwrap() }
145146
}
146147

147148
pub fn system_mut(&mut self) -> &mut dyn System<In = (), Out = ()> {
148-
// SAFE: statically enforced exclusive access.
149-
unsafe { self.system.as_mut() }
149+
self.system.get_mut()
150150
}
151151

152152
/// # Safety
153153
/// Ensure no other borrows exist along with this one.
154154
#[allow(clippy::mut_from_ref)]
155155
pub unsafe fn system_mut_unsafe(&self) -> &mut dyn System<In = (), Out = ()> {
156-
&mut *self.system.as_ptr()
156+
self.system.get().as_mut().unwrap()
157157
}
158158

159159
pub fn should_run(&self) -> bool {

0 commit comments

Comments
 (0)