-
-
Notifications
You must be signed in to change notification settings - Fork 3.8k
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
Bevy, on Web and WebGL, doesn't exit winit's Event Loop cleanly after a GPU crash. It panics twice with already borrowed: BorrowMutError #12979
Comments
Without diving to deep into this, my assumption is that this is a re-entrancy issue, ergo after a panic you should not re-enter the Wasm module. See rust-lang/rust#117344. Please let me know if I got this wrong! |
Yes, that's exactly what this is. In native it's impossible that a program panics twice. However, in this case something (the event loop? Some browser's animation frame call back?) is calling the WASM module after it has originally crashed. It is a bit random, and can be influenced by the browser tab being on focus or not. In fact, I have seen the 2nd BorrowMutError panic happen a considerable amount of time after the original panic occurred. Thankfully, despite of its randomness, I was able to find reliable repro steps to reproduce it with this Bevy example, hence I decided to open the issue to share it. |
Just to clarify: this is not something that can be fixed by Bevy or Winit, at least not properly. This is a Rust issue (rust-lang/rust#117344) and should be fixed in Rustc itself. It could also be fixed in |
Yep indeed, thx! And, as an update for Bevy side, I was able to reproduce this problem on Winit's minimal web example with this code, which at least discards Bevy as being the culprit. Because of that, I guess this issue can be closed as not planned to wait for Rustc to fix this in their side. I'll leave that to Bevy maintainers in any case. @daxpedda, for the same reason, I guess it is not necessary to open the same issue to Winit with these steps to reproduce (the repro steps in the code linked above), right? Let me know if you think otherwise 🙂 |
Hey @daxpedda, can I make you a question about this? If I understand it correctly, what is happening here is that the Rust's WASM module panics, but later on "something" calls into it again. This "something" is, in this case, the browser. Winit's evt loop subscribes to a callback from web_sys, and the problem is that, when the app panics, it never has the chance to unsubscribe from it, right? So, when that callback is called next, after the panic, it panics again because of this So, my question is, if I'm correct about this, shouldn't this be handled by Winit, by setting up a panic hook that unsubscribes from this callback? |
Your description of the problem is correct.
Panic hooks can only be set by the application, not a library. For arguments sake, Winit could find a way to unhook all events when at least panicking inside of Winit itself, though this would be difficult and introduce significant code complexity. It doesn't really solve the problem, if the user panics or any other library, it would hit the same issue again. Bevy itself uses other libraries that hook up into events, e.g. Wgpu. If you are using Egui you would also hit similar problems. It is safe to say that any reasonable solution to this problem has to live in either Rustc or |
You sure? Bevy set ups its own one here: bevy/crates/bevy_log/src/lib.rs Lines 202 to 208 in aa80e2d
I don't know what happens when user code set ups its own. Is it overriden? They can be chained with update_hook or take_hook
totally true, I gave a quick try to this myself and I wasn't able
Oh, really? I didn't know that, I thought a installed panic hook was called for any code panicking in that thread, like being totally global, not per library.
Yep. There is something I don't still get about that core solution: if the WASM module get poisoned after a panic so that it cannot be accessed further in any way, what will happen when a browser callback calls into it like it's currently happening? Will it throw an exception? If that's the case, from the JS point of view, won't it be the same, just with a different type of exception? I found this stack overflow answer to what I think is the same issue, but it sounds too easy to be true, just using the |
Apologies, I meant "should". While it is true that Winit could "update" the panic hook, instead of overwriting it, it would be difficult to remove it again after Winit is finished. If Winit does this, other libraries might want to do the same, registering multiple competing panic hooks which would be difficult to remove/untangle again. Among other reasons, e.g. users should ultimately be in control of what happens in case of a panic, it is not recommended to set the panic hook in libraries (though I couldn't find that in the Rust API guidelines).
I meant versus trying to unhook all event listeners when panicking inside of Winit.
It would trap, which in JS land is exposed as an exception. I think you mean to say that this isn't ideal, which I agree to. This will probably only be totally solved when Rust Wasm moves to the component model 🤞, which supports module poisoning.
I didn't look too closely at this, but I think this was specifically talking about |
ook gotcha, all clear now, thx! 🙂🙏 |
Bevy version
Latest released Bevy atow, which is 0.13.2
This can be reproduced at the Bevy examples posted on the web
Relevant system information
I am able to reproduce this both with Google Chrome and Firefox, both in a M1 Macbook and a Windows 11 laptop
What you did (repro steps)
Now, let's reproduce the actual issue
document.querySelector("#bevy").getContext('webgl2').getExtension("WEBGL_lose_context").loseContext()
wgpu
,glow
, and graphics code, like this:Unexpected behaviour comes here.
BorrowMutError
panic. See:wasm_example.js:502 panicked at [...]/winit-0.29.15/src/platform_impl/web/event_loop/runner.rs:625:30: already borrowed: BorrowMutError
What went wrong
- what were you expecting?
I was expecting to see a single crash. This is needed in production environments to uniquely report crashes for analytics and error tracking, and avoiding redundancies.
- what actually happened?
Winit seems to be exiting the event loop in a wrong way, causing yet another panic, which is then handled by the
console_error_panic_hook
and logged as wellAdditional information
chrome://gpucrash/
in the address bar and press enter to simulate it at a browser level. Same happensThe text was updated successfully, but these errors were encountered: