Apparent misuse of scoped-tls, only appearing on a Raspberry Pi
KnorrFG opened this issue · 19 comments
Hi, I'm trying to run a GUI application (using Iced) on a Raspberry Pi 4B with the latest RPI Os. I didn't modify it yet.
The program crashes before any gui is created, with the following backtrace:
thread 'main' panicked at /home/neuro/.cargo/registry/src/index.crates.io-6f17d22bba15001f/scoped-tls-1.0.1/src/lib.rs:168:9:
cannot access a scoped thread local variable without calling `set` first
stack backtrace:
0: std::panicking::begin_panic
1: scoped_tls::ScopedKey<T>::with
2: wayland_backend::sys::client_impl::dispatcher_func
3: <unknown>
4: <unknown>
5: wl_display_dispatch_queue_pending
6: wl_display_roundtrip_queue
7: <unknown>
8: <unknown>
9: <unknown>
10: <unknown>
11: wgpu_hal::vulkan::instance::<impl wgpu_hal::Surface<wgpu_hal::vulkan::Api> for wgpu_hal::vulkan::Surface>::configure
12: wgpu_core::device::global::<impl wgpu_core::global::Global<G>>::surface_configure
13: <wgpu::backend::wgpu_core::ContextWgpuCore as wgpu::context::Context>::surface_configure
14: <T as wgpu::context::DynContext>::surface_configure
15: wgpu::Surface::configure
16: <iced_wgpu::window::compositor::Compositor as iced_graphics::compositor::Compositor>::configure_surface
17: <iced_wgpu::window::compositor::Compositor as iced_graphics::compositor::Compositor>::create_surface
18: <iced_renderer::compositor::Compositor as iced_graphics::compositor::Compositor>::create_surface
19: core::ops::function::impls::<impl core::ops::function::FnMut<A> for &mut F>::call_mut
20: winit::platform_impl::platform::wayland::event_loop::EventLoop<T>::pump_events
21: winit::platform_impl::platform::wayland::event_loop::EventLoop<T>::run_on_demand
22: iced_winit::application::run
23: ts_updater::gui::gui_main
24: ts_updater::main
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
The crash originates in scoped-tls, but it seems more like a bug in wayland_backend
.
I will append a text file with all logging output. The same program runs perfectly fine on my desktop btw.
Interesting that this only happens with the Raspberry Pi. I guess it's using a proprietary graphics driver rather than the open source Mesa driver?
(Since the graphics driver makes some Wayland calls of its own, and with Mesa that code should be the same as on x86 desktops.)
As far as I can tell, the Raspi is using Mesa, the precise driver seems to be called VideoCore 6, from what I could gather from the internet. Also there is quite some mesa packages installed by default:
neuro@raspberrypi:~ $ dpkg --get-selections | grep mesa
libegl-mesa0:arm64 install
libgl1-mesa-dev:arm64 install
libgl1-mesa-dri:arm64 install
libglapi-mesa:arm64 install
libgles2-mesa:arm64 install
libglu1-mesa:arm64 install
libglu1-mesa-dev:arm64 install
libglx-mesa0:arm64 install
mesa-utils-bin:arm64 install
mesa-vdpau-drivers:arm64 install
mesa-vulkan-drivers:arm64 install
vulkaninfo
should show what Vulkan driver(s) are present. Maybe the Mesa driver is the only Vulkan driver for the Raspberry Pi anyway.
It's odd that the same code would work on everything except the Raspberry Pi, then. Since nothing should really be different.
The output is quite large, so I'll attach it as a text file.
I don't know how video drivers are structured, but it seems VideoCore is something Raspberry Pi specific, that is somehow part of Mesa, so I'd assume there is actually code that is only executed on the raspi.
VkPhysicalDeviceDriverProperties:
---------------------------------
driverID = DRIVER_ID_MESA_V3DV
driverName = V3DV Mesa
driverInfo = Mesa 23.2.1-1~bpo12+rpt3
Yep, it's the V3DV Mesa driver.
it seems VideoCore is something Raspberry Pi specific, that is somehow part of Mesa, so I'd assume there is actually code that is only executed on the raspi.
Yeah. But the code that makes Wayland calls is shared for all Vulkan implementations in Mesa (https://gitlab.freedesktop.org/mesa/mesa/-/blob/main/src/vulkan/wsi/wsi_common_wayland.c).
So it's not obvious what would be different that could change the behavior of wayland-rs.
Could you provide the output of running the app until crash with the env variable WAYLAND_DEBUG=1
set?
Sure: wayland_errors.txt
There are two very puzzling things in that log that maybe you can clarify regarding your app:
- It looks like the debug logs of two programs are mixed together, does your app spawn another program by chance, or does it create two separate Wayland connections?
- If seems in this log that the program creates something like of dozen of Vulkan contextes. Is this expected?
This is absolutely not expected. The app basically doesn't execute any code I've written before the crash, this is all just startup code. I just created an empty iced app skeleton, that does about nothing. Here is the source:
use iced::{executor, widget::Text, Application, Command, Element, Settings, Theme};
#[derive(Debug)]
struct Gui;
#[derive(Debug, Clone)]
pub enum Message {
Foo,
}
impl Application for Gui {
type Executor = executor::Default;
type Flags = ();
type Message = Message;
type Theme = Theme;
fn new((): ()) -> (Gui, Command<Self::Message>) {
(Gui, Command::none())
}
fn title(&self) -> String {
String::from("Foo")
}
fn update(&mut self, message: Self::Message) -> Command<Self::Message> {
Command::none()
}
fn view(&self) -> Element<Self::Message> {
Text::new("hi").into()
}
}
fn main() {
Gui::run(Settings::with_flags(())).unwrap();
}
I just ran that on the pi, with the same result. The wayland log differs slightly: we2.txt
the only dependency you need to add to compile it, is iced itself. As a side node: I cross compile it from an amd64 host in a docker container that runs debian bookworm. The crosscompiler is gcc-arm-linux-gnueabihf
If you run e.g. alacritty or winit example does it work?
Both work, but this problem is vulkan specific, and Alacritty uses OpenGL. And the winit example also does not use vulkan as far as I can tell.
What about the examples for wgpu?
Is it wayfire
that the Raspberry Pi is using as a compositor?
Yes, I think the compositor is wayfire. I'm sorry, but I'm traveling now for 1-2 weeks. I might be able to get my fingers onto a Pi in that time, but I doubt it. I'll try everything that will comes up here in the meantime when I'm back. I still will answer questions that I don't need a pi for though.
Hey, I'm back. The basic WGPU example worked. I ran it via wgpu-examples hello_triangle
. I wasn't able to verify that it actually uses vulkan though, although that might very well be the case.
Just in case it's useful, here is the wayland debug log:
wayland.log
I wonder if zink works with e.g. alacritty/glutin's window example or crashes the same way.
I was able to reproduce this issue on a newly flashed Rpi CM4
thread 'main' panicked at 'cannot access a scoped thread local variable without calling `set` first', scoped-tls-1.0.1/src/lib.rs:168:9
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
It it definitely timing dependent. Like on the other platform I observed this, it seems to only happen when the compositor sends an event before/during the driver dispatches its initialization logic.
#738 fixes the issue on the Rpi CM4
@KnorrFG can you verify that it also fixes the issue you observed?
Patching wayland-backend in the Cargo.toml should work (at least for the minimal example you provided it does)
[patch.crates-io]
wayland-backend = { git = "https://github.com/cmeissl/wayland-rs.git", rev = "34560ffeaced015a891453f00377aa6a1284b86b" }
Hey,
yes this patch fixes it on my Raspberry. For the minimal example as well as for the real application. Thank you.