-
Notifications
You must be signed in to change notification settings - Fork 51
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
Refine the safe window handle API #111
Comments
Not really, it'll raise a protocol error if you do that before the role object and it is not exposed. So while you can issue a drop, you'll kill the entire app. |
Well, on X you could just delete a window in safe code, in a different process, on a different machine connected to the same X server, right? You can't really rely on anything behaving particularly consistently on X unless all clients are cooperative, but it should still be safe at least. On Wayland, yeah, if you destroy the role object and other things the protocol states should be destroyed first. Then I think you could get send requests with an object ID that is no longer valid? Which probably means a protocol error, unless it has been re-used for another surface. The documentation should probably specifically call out these things the API cannot guarantee. |
The |
On Windows, someone can just plain delete your window on you. You don't need to have even shared the HWND with any other code, there's functions to enumerate all visible windows for example. From a separate process even. (If you use a window handle to a deleted window it's supposed to just give "invalid handle" errors, but it's a hard to test edge case so i wouldn't be surprised if possible bugs occurred.) I'm not sure how this "active" thing interacts with that |
Ah, that's a thing on Windows too? Even from another process? I guess it makes sense since the core of the win32 API for dealing with windows is largely the same as the win16 API included in Windows 1.01 in 1985, so it's not particularly more modern than X... So basically this API does not guarantee that the handle is a valid handle for a window that still exists (it should be, but there are these edge cases, on many platforms), but does guarantee it doesn't include an invalid pointer on platforms like Wayland where the The last point here is the subtle one. This API is mostly only useful if we can be sure that it's safe to use wgpu, glutin, and softbuffer with the handle, for all platforms and all API backends of wgpu/glutin. So what soundness requirements do we need to be concerned with for using WGL, GLX, CGL, EGL, Metal, DX12, etc. with the window and display handle... |
I can say that Vulkan builds into it the idea that the surface could explode at any time, and so there's an error code for that which can be appropriately handled by wgpu's vk backend. The other backends, I dunno. |
I think that, as a safety requirement, we should say that any window that consists of an ID (XID on X11, The |
Definitely something to confirm before releasing this. We wouldn't want to release an awkward API that doesn't even succeed at enforcing the safety property its trying to enforce. In particular, if the window can disappear "at any time", that means in some future iteration of the main loop, and not while our local code block is running? Because if it really were "at any time" in the strict sense (between any two CPU instructions where the process is pre-empted, or at exactly the same time on another core) this type isn't able to enforce much. And using the handle in this case is UB, and not just going to produce errors? |
Modern Windows uses generational indices, where some of the bits are the actual index, and the rest of the bits are just a counter that goes up each time the index is used. That way it would take an extremely long time before an |
The thing is that winit is passing the |
I decided to take a run at integrating the new safer API into The main issue here is that My knee jerk reaction would be to split |
Actually, thinking about it, it might be possible to just do this at the start of the program: Box::leak(EventLoop::new()).active().unwrap() to get a free |
Good point. Another possible safety concern: what happens when a |
The idea is that an My goal with this API is that downstream users shouldn't have to change their externals APIs, aside from replacing the An alternative idea is to have an A third option, and one that I like better that the other two, would be to treat the Any other potential strategies? |
I think for that to work it would need to be provided in a lifetime-restricted argument of the callback passed to something like winit's This is similar to how Also, would this active state would be global to the process on Android? With things like Wayland there's no reason you can't have several different Wayland connections in process (each with any number of windows) and no way to distinguish at a type level which one
If That kind of thing can also simply work with refcounting, where the resource isn't destroyed until all (strong) references are dropped. But I'm not familiar with exactly how this works in Android. |
I created #116, which implements the ref-counting mechanism I described here. |
I wrote a blog post about this and posted it to Reddit, where @fleabitdev pointed out a section in the
So I don't think we have to worry about this on Windows, thankfully. |
Any process can send your window a |
Slint is a UI toolkit, it may use different backend to implement the actual windowing (for example, winit, but could be something else, including no backend on bare metal). Since the only way to construct a DisplayHandle ( For that reason, i think there should either be a way to construct a empty (or invalid) DisplayHandle safely. Or the |
I already have the methods set to return a pub enum HandleError {
/// Application is inactive.
Inactive,
/// Raw window handle error.
Raw(RawHandleError)
} ...and then, if we move forwards with this, I think that it should return However, it might be nice to have an |
What prevents HasDisplayHandle::display_handle and HasWindowHandle::window_handle to return a Result in 0.5.x ? These traits haven't been released yet. So now is the time to make the change. In addition to HandleError::Inactive there should be a HandleError::Unsupported or something like that, that specify that no handle can be returned because it is not supported or not implemented by the backend. |
0.5.1 is out already, 0.6 is the next breaking update. |
But HasDisplayHandle and HasWindowHandle are not in 0.5.1, so the Result can be added in 0.5.2 and that will not be a breaking change |
Ah, right right. I misunderstood. |
At the current point in time, they do return |
Just realized something; this is a breaking change on Android, since it fails to compile there if the |
I feel like we should be ready for release. @Lokathor When you have a chance, can you publish an |
I should be able to later today. |
Okay, what I meant was "i can do it tomorrow", 0.5.2 is out |
Closing this issue now, since I think we can now say "mission accomplished". |
Sorry for missing this, and the delayed reply - I was on holiday last week and not actively following up on github stuff. I think I may have skipped a beat here and might need to follow the bread crumbs to understand the issue here. There are a few things that make this stuff a little confusing on Android:
It's maybe a bit of a semantics discussion but on Android the window is a thing that's stable across suspend and resume and is generally full screen. It's also not directly referenced when constructing a graphics API surface. Where Android's graphics stack is a bit unusual is that it effectively passes around a swapchain / When we get notified that the Android What this means, on Android, is that you have to re-create graphics API surfaces each time the app resumes. (Such as an EGLSurface, or WGPU surface, or Vulkan VkSurface etc). In this Glutin example I handle that by clearing surface state when suspending, and lazily-recreate when resuming: https://github.com/rust-mobile/rust-android-examples/blob/41e72ca9de45e2add4776ec004f916ad979cf781/na-winit-glutin/src/lib.rs#L386 If you don't you should just get left with a surface that's associated with a stale I might be overlooking something but as far as I knew there wasn't any safety / soundness issue with Android here currently so I'm not currently sure what issue was being addressed here for Android. There used to be a synchronization problem with |
Hi!
Are you sure? The documentation for
I'm aware that there may be some subtlety under the hood here; maybe the window object is still valid, but the buffer queue isn't, like you said. Or maybe the docs just haven't been updated. However, I'd like to avoid going against the docs unless there is an authoritative source that says otherwise. The docs also say:
This is what the
The idea is that the GPU implementation would check the |
I tested this a while ago in #84 (comment) but it means nothing when considering the (I haven't actually verified if you can/may get the same Fwiw it isn't exactly true that Either way both implementations trivially allow the user to keep their Vulkan/GL surfaces/swapchains alive when created from the original handles (but users will find out soon enough that that doesn't work after a resume, if it didn't crash already). Footnotes |
yeah, I think this is a good way of squaring why the |
I'm not sure this is really the result you get from the E.g. as noted here: #110 (comment) any surface you create is also going to hold a reference to the |
Just to add a bit here, similar to @MarijnS95's comments; Half of what this is referring to is also something that With I tend to think that this needs to be done at an engine/middleware level though. I'm not sure that we can come up with a low level protocol for tearing down graphics surfaces (like |
Hmm, so it seems like the two prescient points are:
If the latter point holds true, then it might be prudent to just remove the @rib and @MarijnS95, I’ll reopen this issue since it seems that there’s more to discuss here. In order to prevent discussion from being scattered across a bunch of PRs and issues, could we keep it here? |
As of #118, I think we're all good here. We've now gotten a healthy selection of platform maintainers to take a look at this system and I think we've patched all the holes. I'll give it a week for anyone else to raise any concerns, just to be safe. |
@notgull FYI I haven't played with the the new |
Given the uh, "other events" going on in Rust(tm) lately I think we should extend the time here by a fair bit. |
Ach, fair point. I'll wait until the trademark issue reaches a reasonable conclusion. |
I think these issues have been resolved, and that we've had plenty of time for discussion here. Would you think that a release is in order? |
I'd still like to address the #104 so we would have a breaking changes packed into a single release. |
Finalized in #126 |
In #110 I added safer versions of the window handles. However, we might need to make sure they work with all platforms, present and future, before we release them.
Platform specific issues that I'm aware of:
Active
to work around that by only allowing usage of the handles while the application is active.BadWindow
error. However, I'm not sure if there are any implications on the GPU end that we should be aware of.The text was updated successfully, but these errors were encountered: