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
Attempt to fix a panic in accesskit #3046
Conversation
On unix, the panic happens since the upgrade from zbus 3.10 to zbus 3.14 ``` thread 'test_window_accessor' panicked at 'called `Option::unwrap()` on a `None` value', /home/olivier/.cargo/registry/src/index.crates.io-6f17d22bba15001f/accesskit_consumer-0.15.0/src/tree.rs:274:45 stack backtrace: [...] 3: core::option::Option<T>::unwrap 4: accesskit_consumer::tree::Tree::new at /home/olivier/.cargo/registry/src/index.crates.io-6f17d22bba15001f/accesskit_consumer-0.15.0/src/tree.rs:274:19 5: accesskit_unix::adapter::Adapter::new at /home/olivier/.cargo/registry/src/index.crates.io-6f17d22bba15001f/accesskit_unix-0.5.0/src/adapter.rs:53:20 6: accesskit_winit::platform_impl::platform::Adapter::new at /home/olivier/.cargo/registry/src/index.crates.io-6f17d22bba15001f/accesskit_winit-0.14.1/src/platform_impl/unix.rs:21:23 7: accesskit_winit::Adapter::with_action_handler at /home/olivier/.cargo/registry/src/index.crates.io-6f17d22bba15001f/accesskit_winit-0.14.1/src/lib.rs:170:23 8: i_slint_backend_winit::accesskit::AccessKitAdapter::new at ./accesskit.rs:62:20 9: i_slint_backend_winit::winitwindowadapter::WinitWindowAdapter::new::{{closure}} at ./winitwindowadapter.rs:163:32 10: alloc::rc::Rc<T>::new_cyclic at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/alloc/src/rc.rs:461:20 11: i_slint_backend_winit::winitwindowadapter::WinitWindowAdapter::new at ./winitwindowadapter.rs:148:23 12: i_slint_backend_winit::window_factory_fn at ./lib.rs:71:5 13: <i_slint_backend_winit::Backend as i_slint_core::platform::Platform>::create_window_adapter at ./lib.rs:220:9 ``` The problem is that we get called to create the tree directly from WinitWindowAdapter::new before the WinitWindowAdaptor is initialized, So of course, the upgrade from weak is still the pseudo-weak from Rc::new_cyclic, so the upgrade fails, resulting in a default constructed `TreeUpdate` which is invalid for the first call as it doesn't have a tree. Just give it a tree with a dummy id
Please review carefully, I have no idea what i'm doing. |
I see this and will look into it either this evening or tomorrow, after I return home from a trip. |
I wonder how this ever worked, now that I see this. If connecting to the a11y bus fails, AccessKit returns and never calls the initial tree state function. That must've happened before, somehow. The fact that it happens for you seems like a bug, unless perhaps you do have an at-spi bus running on your system? But what's worse is this when there is intentionally a bus running, the current code will indeed always panic - due to the symptoms you described. On Windows and macOS the callback is invoked later, but AccessKit behaves different on Linux here. In other words: this never worked :( This patch works around the panic successfully, but I'm concerned it breaks it breaks the case when an accessibility tree is really wanted: we must make sure to deliver a new and complete tree later - as a workaround for the AccessKit_unix behavior. That workaround is missing in this patch AFAICS. |
In a way it would be nice if AccessKit on Linux also called the initial tree callback at a later point, but I can see that this is not documented behavior. So the only other solution I can see is to delay the creation of the AccessKitAdapter on our end at a later point. |
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.
I think this fixes the panic on Linux and it should not impact windows and macOS as there by the time it is invoked the window adapter upgrade should work.
When accessibility on Linux is really needed, this won’t panic anymore but I think the initial tree will be completely wrong unless an update replaces it. But that’s not worse than panicking as before.
I don't. It started failing when upgrading from to zbus 3.14 (It was using zbus 3.10 before (that's what in the Cargo.lock for the 1.1.0 release for C++). intermediate version of zbus are not selected by Cargo because zbus was pinning a dependency in a way that would make the dependency resolution fails) IMHO AccessKit should not query the tree unless there is an actual at-spi bus active. Otherwise we pay the overhead for nothing. (In light of that, i wonder if we should really have the feature on by default) |
Please do not disable the feature by default. I was willing to allow the Unix adapter in particular to be disabled by default in the Bevy game engine due to that adapter's impact on code size and dependency count, because for the most part, games will not be automatically accessible anyway. But in a general-purpose GUI toolkit, accessibility should be enabled by default, so we don't have to beg every application developer to turn it on. We do try to minimize the overhead of AccessKit when accessibility is not being used, but in this case, it does look like @ogoffart must be running an AT-SPI bus. Creating a dummy tree if the callback is called immediately is fine, as long as it's guaranteed that a tree update with a real tree will be issued very soon afterward. I don't know enough about slint to know if that's the case. Please check this. Finally, the dummy tree update should include an entry for the dummy node with ID 1 in the |
Yeah, that's a valid point. But it's also not enabled by default in egui.
I am not. (at least i didn't setup one, i don't think it's the case) Perhaps it is a bug in zbus that do not report errors while it should?
Also, it appear like accesskit will do blocking dbus when the window is shown. (if i'm not mistaken) Perhaps that's not critical, but that's also not ideal. With winit, it is possible to write a Waker that calls winit::event_loop::EventLoopProxy.
yeah, do we really need to have a valid tree at start? Could accesskit not allow None as a tree, and we would call an update with a new tree later when we have one? |
It's true that the base egui crate has AccessKit disabled by default, and I accepted that because in many projects that use egui, particularly in many projects with custom egui integrations, accessibility is likely to be impractical anyway. However, in the higher-level eframe crate, AccessKit is enabled by default. I believe that slint is more like eframe than the base egui crate. Having an initial tree with a dummy root node is the accepted workaround for cases where the callback is called too early. It's what I did in eframe. Please add the dummy root node. I'm not sure it would be a good idea to complicate AccessKit itself to deal with this situation. Also, I need assurance that a tree update with a real, non-empty tree is guaranteed to be issued soon after the initial dummy tree. |
@ogoffart I recognize that this PR is probably not the right place to discuss the unexpected fact that AccessKit is active on your machine even though you're not running an assistive technology, and to decide what we're going to do about it. But we have to discuss it somewhere, and I can't accept turning AccessKit off by default. What do you propose? Do you want to start a discussion thread or open an issue? |
I'm quite sure that the AccessKit Unix adapter will not call the tree source callback unless the adapter successfully connects to a running AT-SPi bus. @ogoffart Can you please check whether |
Yes you're actually right, i have at-spi2-registryd running. |
OK, now I'm wondering if AccessKit's current behavior is wrong. Maybe the socket-activated startup of the AT-SPi registry was only intended to allow assistive technologies to lazily activate the registry, not applications. @federicomenaquintero Can you please clarify how this is supposed to work? If AccessKit's behavior is wrong, then I'll open an AccessKit issue and get it fixed as quickly as possible. |
Applications are meant to do this:
Step (2) will launch the accessibility bus on demand. Step (4) will launch the atspi registry daemon on demand. If you want to play with things by hand, you can accomplish step 2 by running this on the command line:
If you then look at a process listing, you should see something like this:
Note that that is not the usual You will also see a
The lifetime of those three daemons (at-spi-bus-launcher, the accessibility dbus daemon, and at-spi2-registryd) is controlled by the user's session, that is, they use the gnome-session dbus protocol to be notified when the session is terminating and they should exit. Please see this script from at-spi2-core's CI for inspiration; it uses a mock gnome-session, but the |
I'm going to go ahead and merge this for now because more and more users are reporting the panic. |
We need to make sure to replace the dummy tree from #3046 with a real tree.
We need to make sure to replace the dummy tree from #3046 with a real tree.
On unix, the panic happens since the upgrade from zbus 3.10 to zbus 3.14
The problem is that we get called to create the tree directly from WinitWindowAdapter::new before the WinitWindowAdaptor is initialized, So of course, the upgrade from weak is still the pseudo-weak from Rc::new_cyclic, so the upgrade fails, resulting in a default constructed
TreeUpdate
which is invalid for the first call as it doesn't have a tree.Just give it a tree with a dummy id