-
Notifications
You must be signed in to change notification settings - Fork 277
Fix stack overflow on audio change #285
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix stack overflow on audio change #285
Conversation
2ea902b to
99c0c36
Compare
|
Ok I managed to reproduce it as per the above. My goal is to determine a correlation between the length of I added the following right at the start of fn drop(&mut self) {
let mut count = 0;
let mut cursor = self.next.lock().unwrap().clone();
loop {
if let Frame::Data(data) = &*cursor.clone() {
let next = data.next.lock().unwrap();
cursor = next.clone();
} else {
break;
}
count += 1;
}
println!("count: {}", count);
return;
......to measure the length of the chain. As an added bonus, the above code runs every time one of the nested No crash:
Crash:
Then I got rid of the |
Drop for FrameData0650ba2 to
a68f146
Compare
The types `Frame` and `FrameData` are mutually recursive, and the incidental linked lists that can be formed as a result can be long (at least in the order of thousands of elements). As a result, when a frame is deallocated, rust appears to recursively call `drop_in_place` down the list, causing stack overflows for long lists.
a68f146 to
b1606ee
Compare
|
Squashed fix up commits and rebased onto the tip of master |
|
@nicokoch any thoughts on whether this change is ok to merge? Would you like me to rebase it onto master? |
|
Bump? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok except for detail. Sorry for the delay.
| // the `next` field will contain a `Frame::End`, or an `Arc` with additional references, | ||
| // so the depth of recursive drops will be bounded. | ||
| loop { | ||
| if let Ok(arc_next) = self.next.get_mut() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This can be turned into a while let, no?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This has sat unreviewed for more than a year. I'm merging despite the small issue. Subsequent PRs for improvement are welcome!
|
Thanks for the merge @est31! I'll make the change you suggested in a subsequent PR. |
The types
FrameandFrameDataare mutually recursive, and theincidental linked lists that can be formed as a result can be long (at
least in the order of thousands of elements). As a result, when a frame
is deallocated, rust appears to recursively call
drop_in_placedownthe list, causing stack overflows for long lists.
Addresses #283
This problem is hard to reproduce. I've tried constructing toy programs to no avail. The only way I've managed to trigger it is running https://github.com/stevebob/slime99/
graphicaloransi-terminalcrates with the--audioflag (audio is disabled by default because of exactly this problem). Start a new game and leave it on the first floor for ~5 minutes, then walk down the stairs. The track will switch and sometimes there will be a stack overflow on the "rodio audio processing" thread.I was able to reliably reproduce the problem last night, but I'm trying to again now (after changing nothing) and it's not happening. Something something phase of the moon. In other words, I'm not satisfied with my testing of this patch thus far. I'm opening this PR now to start a discussion. Is there a way to construct a long chain of
Frame->FrameData->Frame->...? I think doing so would reliably trigger this problem.