-
Notifications
You must be signed in to change notification settings - Fork 948
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
On Windows, fix request_redraw() related panics #1461
Conversation
521c2d0
to
1617ad7
Compare
1617ad7
to
de54072
Compare
3bb98f3
to
b16ff93
Compare
b16ff93
to
dc354c2
Compare
37141ef
to
6659f8f
Compare
I think I am done for now. All reported panics are not reproducible anymore. |
I'm guessing it probably also fixes #1469 |
Windows user experienced some panics.
and
edit: updated with debug info versions |
@Imberflur what was the user doing and which Windows version was used ? I think I understand the issue but can't reproduce it. See #1429 (comment). And where can I find the source code to take a look ? Edited: Might be triggered by something done while handling MainEventsCleared in the user event loop. |
Here is the event loop code: https://gitlab.com/veloren/veloren/-/blob/zesterer/winit-20/voxygen/src/run.rs |
I was able to get a panic by sleeping when handling @Imberflur your first panic has this strange line:
Line 0 ??? |
@Imberflur not sure it is going to address your issues but in your game loop, you should: |
@filnet I avoided using the "correct" method for redrawing because it kept the code simpler/closer to the original structure and I don't have the need currently to respond to external redraw requests. Nevertheless, I doubt it would circumvent the issue since time would still be spent in |
19e2307
to
801f11d
Compare
I just pushed a small fix that should address some of the panics. |
I am more or less done now. But there are two aspects that I am not too happy about. 1/ I added a few panic calls to catch some undefined use cases. Edit: likewise, calling 2/ There is a handful of calls to |
I believe the desired usage is that you enter the eventloop and it takes over as your With that said, I'd imagine that the expectation for state change operations like |
Yep and that's the whole point. Because of how winit does things on Windows handling There is a sort of catch 22 situation. Calling Anyways, if I change the |
To summarize the situation: winit forwards native UI events and also injects a few synthetic events ( The synthetic events act as some sort of checkpoints. Unfortunately, winit cannot forbid user code from changing the window state from The doc should be updated to mention that some use cases are discouraged and have undefined behaviors. Edit: https://docs.rs/winit/0.21.0/winit/event/enum.Event.html |
We could change EDIT: the |
There is no proper fix in my opinion. The doc tells you what you're supposed to do when handling
To me, it is implied that doing anything else will result in undefined behavior. And the "updating state" refers to your "world state", not the window state. The problem is that the user code has full access to the window. Ideally it should have access to a mutable window when handling regular events and to a non mutable events when handling An extreme example: In This quite long video mentions this issue (in another but similar context) : https://www.youtube.com/watch?v=4YTfxresvS8 |
I think what is allowed to be done in Also note that all winit's example call state changing function (set_fullscreen, etc) when handling keyboard events. They never do it from Now the real question, since we can't prevent it, is how to handle it : crash, warn or fumble. |
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 are a couple code quality concerns I have with this, but functionality-wise this looks good. Thank you for investigating these problems!
@filnet My stance is that calling any window state-changing function during |
@Osspial I'll try to put this PR in perspective. I came to winit as I decided to learn Rust and port a pet project (a Voxel engine in Monogame) to it. I then fell into the rabbit hole of trying to fix the issues introduced in this major release. AFAIK, the two major issues remaining, in 0.21.0 and this PR, are: |
These panics were introduced by rust-windowing@6a330a2 Fixes rust-windowing#1391 Fixes rust-windowing#1400 Fixes rust-windowing#1466 Probably fixes other related issues See rust-windowing#1429
This avoids directly sending a WM_PAINT message, which might cause buffering of RedrawRequested events. We don't want to buffer RedrawRequested events because: - we wan't to handle RedrawRequested during processing of WM_PAINT messages - state transitionning is broken when handling buffered RedrawRequested events Fixes rust-windowing#1469
This fixes a panic. Note that the WM_PAINT event is now sent to the modal_redraw_method which is more correct and avoids an unecessary redraw of the window. Relates to but does does not fix rust-windowing#1484
This seems to prevent PeekMessage from dispatching unrelated sent messages
This makes the code less panicky... And actually, winit's Windoww callbacks should not panic because the panic will unwind into Windows code. It is currently undefined behavior to unwind from Rust code into foreign code. See https://doc.rust-lang.org/std/panic/fn.catch_unwind.html
e145f74
to
f346b43
Compare
Alright, this looks good. Thanks for the work on this! I'll go ahead and merge this now, since it seems to be a bit more stable than #1496 is at present. That being said, I still intend to merge #1496 eventually, once the issues with it have been addressed. There are a good number of concrete technical reasons to go to the additional lengths that PR does, but it'll be better to explain those in that particular thread. |
Simplifies the message loops and event handling considerablyStrongly inspired from the X11 platformPartially reverts 6a330a2These panics were introduced by 6a330a2
Fixes #1391
Fixes #1400
Fixes #1466
Fixes #1469
Probably fixes other related issues
The commit mentioned above introduced a few critical regressions.
I did quite a bit of forensic (looking at 0.19.1, 0.20.0-alpha1) to understand what was going on around the handling of request_redraw(). I also looked at how other platforms handle it.
I tried really hard to fix the issues using the current approach of posting WM_PAINT messages but got nowhere. Too many corner cases.In the end I decided to go for the X11 approach of using a HashSet to keep track of windows requiring a redraw and things got much simpler.
This PR does not fundamentally change how request_redraw() is handled.
It still calls
RedrawWindow
which sends aWM_PAINT
message. Which means that:WM_PAINT
messages are coalesced (for example when calling request_redraw while resizing or calling request_redraw multiple times),RedrawRequested
events are always sent when handling aWM_PAINT
message.I tried to be very thorough in testing:
There are a few untested corner cases. See #1429 for more details.
And always kept the specs in a corner of my mind:
https://docs.rs/winit/0.21.0/winit/window/struct.Window.html#method.request_redraw
https://docs.rs/winit/0.21.0/winit/event/index.html
Tested on all platforms changed
Compilation warnings were addressed
cargo fmt
has been run on this branchcargo doc
builds successfullyAdded an entry to
CHANGELOG.md
if knowledge of this change could be valuable to usersUpdated documentation to reflect any user-facing changes, including notes of platform-specific behavior
Created or updated an example program if it would help users understand this functionality
Updated feature matrix, if new features were added or implemented