-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
[egui_web] Prevent event handlers from running if code has panicked #1306
Conversation
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.
LGTM works fine on my end. Very useful imo!
@Titaniumtown can you show the code that caused this panic so I can look into it? |
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.
Looks good - thanks!
impl AppRunnerContainer { | ||
/// Convenience function to reduce boilerplate and ensure that all event handlers | ||
/// are dealt with in the same way | ||
pub fn add_event_listener<E: wasm_bindgen::JsCast>( |
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 is great!
I'll wait with merging this until @Titaniumtown gets back |
Oh I'll send a code snippet in a bit. |
Ok. So when interacting with buttons and an input text box like so: https://github.com/Titaniumtown/integral_site/blob/d48b94c1d2a43d0fab4ebba630d315f82cd5553b/src/egui_app.rs#L277 then https://github.com/Titaniumtown/integral_site/blob/d48b94c1d2a43d0fab4ebba630d315f82cd5553b/src/egui_app.rs#L298 and interacting with one, then another. I get that error. This error doesn't occur on the master branch. It seems to be related to the entire thing being wrapped in a |
It works now! (at least for me) |
@Titaniumtown I think I have fixed your panic issue with the new commits I have pushed. Please try them out on your setup to make sure it works not just on my machine. The root cause is some very weird wasm/js-engine tomfoolery that must be going on, causing an event handler to interrupt the Note: the CI has started failing, but this seems to be caused by a new advisory for the |
I've tested it on mobile, and mobile text input still works, so… looks good to me! |
I just noticed a bug caused by this PR: resizing the browser window will no longer immediately resize the egui canvas, making it feel VERY unresponsive. |
Fix copy-paste error introduced in #1306
…#1306) Closes: #1290 Fix panic reported by @Titaniumtown See emilk/egui#1306 (comment)
…#1306) Closes: #1290 Fix panic reported by @Titaniumtown See emilk/egui#1306 (comment)
The way egui_web works involves adding event handlers to a
<canvas>
element, the<body>
, and a helper<input>
element. By setting up such callbacks, it creates a position where the JavaScript/WASM runtime will call rust code across a FFI boundary, but that rust code could be in an invalid state, due to a previous panic. More information on the issue can be seen in #1209.There are 2 ways to prevent this problem from occuring:
std::panic::catch_unwind
The first option would be preferable since it would allow for the user to have more control over the de-registering of the callbacks. This was my first attempt but it became hard to near impossible.
egui
andegui_web
are notUnwindSafe
orRefUnwindSafe
which make usingstd::panic::catch_unwind
impossible.wasm_bindgen
,web_sys
, orjs_sys
areSend
. This means that there would be no way for a panic handler (std::panic::set_hook
) to be passed thejs_sys::Function
or even theweb_sys::EventTarget
. both of which are needed to callremove_event_listener
.Both of the above limitations mean that the event listeners can not be de-registered from inside of a panic handler. This leaves only option 2.
The way I have implemented this is using a shared
Arc<AtomicBool>
between all of the event handlers and the panic handler. Every time the event handlers are called, they perform aAtomicBool::load(SeqCst)
and check that the bool is false. If it is, they continue calling the normal rust code. If the bool was true, the event handler returns early. TheAtomicBool
is set to true by the panic handler as soon as it is hit, so all callbacks after will be skipped.In making this change, I created a convenience method that will wrap the callbacks in a check against the atomic bool as well as reduce boilerplate with closure creation, event listener adding, and closure forgetting.
There is only one event listener I did not touch, and that is the contextmenu event handler. Since this handler does not call into any egui code, it does not contribute to the problem and can be left alone.
The main culprit of the errors is the locking of the mutex guarding the
AppRunner
.Here is a link to a few important changes:
paint_and_schedule
And a before/after comparison:
Before:
before.mp4
After:
after.mp4
As can be seen in the after demo, there is still one
unreachable executed
error, but this is caused by the builtin rust panic handler calling unsupported code so there is nothing I can do about it.Closes #1290.