[Merged by Bors] - fix some memory leaks detected by miri - #4959
Closed
BoxyUwU wants to merge 3 commits into
Closed
Conversation
Member
|
Can we get that command added to somewhere in the docs? |
alice-i-cecile
approved these changes
Jun 27, 2022
alice-i-cecile
left a comment
Member
There was a problem hiding this comment.
Good eye. Nice to see miri catching these problems for us.
bors r+
bors Bot
pushed a commit
that referenced
this pull request
Jun 27, 2022
remove `-Zmiri-ignore-leaks` from CI args and fix leaks that miri detects.
The first leak:
```rust
#[test]
fn blob_vec_drop_empty_capacity() {
let item_layout = Layout::new::<Foo>();
let drop = drop_ptr::<Foo>;
let _ = unsafe { BlobVec::new(item_layout, Some(drop), 0) };
}
```
this is because we allocate the swap scratch in blobvec regardless of what the capacity is, but we only deallocate if capacity is > 0
The second leak:
```rust
#[test]
fn panic_while_overwriting_component() {
let helper = DropTestHelper::new();
let res = panic::catch_unwind(|| {
let mut world = World::new();
world
.spawn()
.insert(helper.make_component(true, 0))
.insert(helper.make_component(false, 1));
println!("Done inserting! Dropping world...");
});
let drop_log = helper.finish(res);
assert_eq!(
&*drop_log,
[
DropLogItem::Create(0),
DropLogItem::Create(1),
DropLogItem::Drop(0),
]
);
}
```
this is caused by us not running the drop impl on the to-be-inserted component if the drop impl of the overwritten component panics
---
managed to figure out where the leaks were by using this 10/10 command
```
cargo --quiet test --lib -- --list | sed 's/: test$//' | MIRIFLAGS="-Zmiri-disable-isolation" xargs -n1 cargo miri test --lib -- --exact
```
which runs every test one by one rather than all at once which let miri actually tell me which test had the leak :upside_down_face:
|
Build failed: |
Member
Looks like there's a warning that should be ignored? |
Member
|
bors retry |
bors Bot
pushed a commit
that referenced
this pull request
Jun 30, 2022
remove `-Zmiri-ignore-leaks` from CI args and fix leaks that miri detects.
The first leak:
```rust
#[test]
fn blob_vec_drop_empty_capacity() {
let item_layout = Layout::new::<Foo>();
let drop = drop_ptr::<Foo>;
let _ = unsafe { BlobVec::new(item_layout, Some(drop), 0) };
}
```
this is because we allocate the swap scratch in blobvec regardless of what the capacity is, but we only deallocate if capacity is > 0
The second leak:
```rust
#[test]
fn panic_while_overwriting_component() {
let helper = DropTestHelper::new();
let res = panic::catch_unwind(|| {
let mut world = World::new();
world
.spawn()
.insert(helper.make_component(true, 0))
.insert(helper.make_component(false, 1));
println!("Done inserting! Dropping world...");
});
let drop_log = helper.finish(res);
assert_eq!(
&*drop_log,
[
DropLogItem::Create(0),
DropLogItem::Create(1),
DropLogItem::Drop(0),
]
);
}
```
this is caused by us not running the drop impl on the to-be-inserted component if the drop impl of the overwritten component panics
---
managed to figure out where the leaks were by using this 10/10 command
```
cargo --quiet test --lib -- --list | sed 's/: test$//' | MIRIFLAGS="-Zmiri-disable-isolation" xargs -n1 cargo miri test --lib -- --exact
```
which runs every test one by one rather than all at once which let miri actually tell me which test had the leak :upside_down_face:
|
Build failed: |
BoxyUwU
force-pushed
the
dont_ignore_leaks
branch
from
July 1, 2022 16:01
22dcb40 to
960a7a8
Compare
-Zmiri-ignore-leaks from miri CI job
Member
|
bors r+ |
bors Bot
pushed a commit
that referenced
this pull request
Jul 1, 2022
The first leak:
```rust
#[test]
fn blob_vec_drop_empty_capacity() {
let item_layout = Layout::new::<Foo>();
let drop = drop_ptr::<Foo>;
let _ = unsafe { BlobVec::new(item_layout, Some(drop), 0) };
}
```
this is because we allocate the swap scratch in blobvec regardless of what the capacity is, but we only deallocate if capacity is > 0
The second leak:
```rust
#[test]
fn panic_while_overwriting_component() {
let helper = DropTestHelper::new();
let res = panic::catch_unwind(|| {
let mut world = World::new();
world
.spawn()
.insert(helper.make_component(true, 0))
.insert(helper.make_component(false, 1));
println!("Done inserting! Dropping world...");
});
let drop_log = helper.finish(res);
assert_eq!(
&*drop_log,
[
DropLogItem::Create(0),
DropLogItem::Create(1),
DropLogItem::Drop(0),
]
);
}
```
this is caused by us not running the drop impl on the to-be-inserted component if the drop impl of the overwritten component panics
---
managed to figure out where the leaks were by using this 10/10 command
```
cargo --quiet test --lib -- --list | sed 's/: test$//' | MIRIFLAGS="-Zmiri-disable-isolation" xargs -n1 cargo miri test --lib -- --exact
```
which runs every test one by one rather than all at once which let miri actually tell me which test had the leak :upside_down_face:
bors Bot
pushed a commit
that referenced
this pull request
Jul 6, 2022
# Objective When `miri` runs in our build system to detect unsoundness, its output can be very unhelpful, as the tests are all run in parallel. ## Solution Add a comment documenting the extremely obvious 10/10 command used by @BoxyUwU in #4959. I've stuck this in the CI file, as it seems like the most obvious place to check when frustrated. I didn't put it in CONTRIBUTING.md because this is an eldritch abomination and will never be useful to new contributors.
inodentry
pushed a commit
to IyesGames/bevy
that referenced
this pull request
Aug 8, 2022
The first leak:
```rust
#[test]
fn blob_vec_drop_empty_capacity() {
let item_layout = Layout::new::<Foo>();
let drop = drop_ptr::<Foo>;
let _ = unsafe { BlobVec::new(item_layout, Some(drop), 0) };
}
```
this is because we allocate the swap scratch in blobvec regardless of what the capacity is, but we only deallocate if capacity is > 0
The second leak:
```rust
#[test]
fn panic_while_overwriting_component() {
let helper = DropTestHelper::new();
let res = panic::catch_unwind(|| {
let mut world = World::new();
world
.spawn()
.insert(helper.make_component(true, 0))
.insert(helper.make_component(false, 1));
println!("Done inserting! Dropping world...");
});
let drop_log = helper.finish(res);
assert_eq!(
&*drop_log,
[
DropLogItem::Create(0),
DropLogItem::Create(1),
DropLogItem::Drop(0),
]
);
}
```
this is caused by us not running the drop impl on the to-be-inserted component if the drop impl of the overwritten component panics
---
managed to figure out where the leaks were by using this 10/10 command
```
cargo --quiet test --lib -- --list | sed 's/: test$//' | MIRIFLAGS="-Zmiri-disable-isolation" xargs -n1 cargo miri test --lib -- --exact
```
which runs every test one by one rather than all at once which let miri actually tell me which test had the leak :upside_down_face:
inodentry
pushed a commit
to IyesGames/bevy
that referenced
this pull request
Aug 8, 2022
# Objective When `miri` runs in our build system to detect unsoundness, its output can be very unhelpful, as the tests are all run in parallel. ## Solution Add a comment documenting the extremely obvious 10/10 command used by @BoxyUwU in bevyengine#4959. I've stuck this in the CI file, as it seems like the most obvious place to check when frustrated. I didn't put it in CONTRIBUTING.md because this is an eldritch abomination and will never be useful to new contributors.
james7132
pushed a commit
to james7132/bevy
that referenced
this pull request
Oct 28, 2022
The first leak:
```rust
#[test]
fn blob_vec_drop_empty_capacity() {
let item_layout = Layout::new::<Foo>();
let drop = drop_ptr::<Foo>;
let _ = unsafe { BlobVec::new(item_layout, Some(drop), 0) };
}
```
this is because we allocate the swap scratch in blobvec regardless of what the capacity is, but we only deallocate if capacity is > 0
The second leak:
```rust
#[test]
fn panic_while_overwriting_component() {
let helper = DropTestHelper::new();
let res = panic::catch_unwind(|| {
let mut world = World::new();
world
.spawn()
.insert(helper.make_component(true, 0))
.insert(helper.make_component(false, 1));
println!("Done inserting! Dropping world...");
});
let drop_log = helper.finish(res);
assert_eq!(
&*drop_log,
[
DropLogItem::Create(0),
DropLogItem::Create(1),
DropLogItem::Drop(0),
]
);
}
```
this is caused by us not running the drop impl on the to-be-inserted component if the drop impl of the overwritten component panics
---
managed to figure out where the leaks were by using this 10/10 command
```
cargo --quiet test --lib -- --list | sed 's/: test$//' | MIRIFLAGS="-Zmiri-disable-isolation" xargs -n1 cargo miri test --lib -- --exact
```
which runs every test one by one rather than all at once which let miri actually tell me which test had the leak :upside_down_face:
james7132
pushed a commit
to james7132/bevy
that referenced
this pull request
Oct 28, 2022
# Objective When `miri` runs in our build system to detect unsoundness, its output can be very unhelpful, as the tests are all run in parallel. ## Solution Add a comment documenting the extremely obvious 10/10 command used by @BoxyUwU in bevyengine#4959. I've stuck this in the CI file, as it seems like the most obvious place to check when frustrated. I didn't put it in CONTRIBUTING.md because this is an eldritch abomination and will never be useful to new contributors.
ItsDoot
pushed a commit
to ItsDoot/bevy
that referenced
this pull request
Feb 1, 2023
The first leak:
```rust
#[test]
fn blob_vec_drop_empty_capacity() {
let item_layout = Layout::new::<Foo>();
let drop = drop_ptr::<Foo>;
let _ = unsafe { BlobVec::new(item_layout, Some(drop), 0) };
}
```
this is because we allocate the swap scratch in blobvec regardless of what the capacity is, but we only deallocate if capacity is > 0
The second leak:
```rust
#[test]
fn panic_while_overwriting_component() {
let helper = DropTestHelper::new();
let res = panic::catch_unwind(|| {
let mut world = World::new();
world
.spawn()
.insert(helper.make_component(true, 0))
.insert(helper.make_component(false, 1));
println!("Done inserting! Dropping world...");
});
let drop_log = helper.finish(res);
assert_eq!(
&*drop_log,
[
DropLogItem::Create(0),
DropLogItem::Create(1),
DropLogItem::Drop(0),
]
);
}
```
this is caused by us not running the drop impl on the to-be-inserted component if the drop impl of the overwritten component panics
---
managed to figure out where the leaks were by using this 10/10 command
```
cargo --quiet test --lib -- --list | sed 's/: test$//' | MIRIFLAGS="-Zmiri-disable-isolation" xargs -n1 cargo miri test --lib -- --exact
```
which runs every test one by one rather than all at once which let miri actually tell me which test had the leak :upside_down_face:
ItsDoot
pushed a commit
to ItsDoot/bevy
that referenced
this pull request
Feb 1, 2023
# Objective When `miri` runs in our build system to detect unsoundness, its output can be very unhelpful, as the tests are all run in parallel. ## Solution Add a comment documenting the extremely obvious 10/10 command used by @BoxyUwU in bevyengine#4959. I've stuck this in the CI file, as it seems like the most obvious place to check when frustrated. I didn't put it in CONTRIBUTING.md because this is an eldritch abomination and will never be useful to new contributors.
pull Bot
pushed a commit
to CrazyForks/bevy
that referenced
this pull request
Jul 14, 2026
# Objective Make it possible to run miri with memory leak detection enabled. It is enabled by default, so it reports errors whenever I run it locally. And running it in CI should help prevent any new leaks from being introduced. See bevyengine#4310 and bevyengine#4959 for previous attempts to enable this. Note that miri has added backtraces to leaked allocations since then (rust-lang/rust#109061), so leaks are much easier to diagnose. ## Solution The first leak: When trying to drop non-send data on the wrong thread, the allocation for the value was being leaked. We can't drop the value from the wrong thread, but we could still deallocate its storage. Rework the thread check in `NonSendData::drop` so that it still deallocates, setting `present = false` to ensure the value's `drop` is not called. Change the `panic!` to a `warn!` so that we can have the check work the same way during unwinding. The second leak: The tests for `Interned` intentionally leak data! So we can't exactly "fix" them, but I'd like miri to stop failing on them. Then I realized that miri does not report leaks for our use of `Interned` for things like `ScheduleLabel`. That's because those values are stored in a `static`, so are still reachable. So, add a `static` to each of the tests with intentional leaks and store the leaked values there. miri will consider those values reachable, and not report any leaks. --------- Co-authored-by: Daniel Skates <zeophlite@gmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The first leak:
this is because we allocate the swap scratch in blobvec regardless of what the capacity is, but we only deallocate if capacity is > 0
The second leak:
this is caused by us not running the drop impl on the to-be-inserted component if the drop impl of the overwritten component panics
managed to figure out where the leaks were by using this 10/10 command
which runs every test one by one rather than all at once which let miri actually tell me which test had the leak 🙃