slint-ui / slint

Slint is a declarative GUI toolkit to build native user interfaces for Rust, C++, or JavaScript apps.
https://slint.dev
Other
17.55k stars 601 forks source link

detect if update_timers_and_animations is called from the wrong thread #3461

Closed ilmai closed 9 months ago

ilmai commented 1 year ago

I'm working on a custom backend, and encountered this panic when I try to test animation. I'm calling update_timers_and_animations() at monitor refresh rate in case that's relevant, which on my Macbook is apparently adaptive and up to 120Hz.

Here's the test component I'm using:

export component HelloWorld {
    rectangle := Rectangle {
        background: area.pressed ? blue : red;
        animate background {
            duration: 250ms;
        }

        area := TouchArea {}
    }
}

Here's the relevant part of the stack trace:

  13: <i_slint_core::animations::Instant as core::ops::arith::Sub>::sub
             at /Users/jussi/.cargo/registry/src/index.crates.io-6f17d22bba15001f/i-slint-core-1.2.0/animations.rs:159:43
  14: i_slint_core::animations::Instant::duration_since
             at /Users/jussi/.cargo/registry/src/index.crates.io-6f17d22bba15001f/i-slint-core-1.2.0/animations.rs:194:9
  15: i_slint_core::properties::properties_animations::PropertyValueAnimationData<T>::compute_interpolated_value
             at /Users/jussi/.cargo/registry/src/index.crates.io-6f17d22bba15001f/i-slint-core-1.2.0/properties/properties_animations.rs:32:33
  16: <i_slint_core::properties::properties_animations::AnimatedBindingCallable<T,A> as i_slint_core::properties::BindingCallable>::evaluate
             at /Users/jussi/.cargo/registry/src/index.crates.io-6f17d22bba15001f/i-slint-core-1.2.0/properties/properties_animations.rs:145:39
  17: i_slint_core::properties::alloc_binding_holder::evaluate::{{closure}}
             at /Users/jussi/.cargo/registry/src/index.crates.io-6f17d22bba15001f/i-slint-core-1.2.0/properties.rs:393:13
  18: i_slint_core::properties::CURRENT_BINDING::<impl i_slint_core::properties::CURRENT_BINDING>::set
             at /Users/jussi/.cargo/registry/src/index.crates.io-6f17d22bba15001f/scoped-tls-hkt-0.1.4/src/lib.rs:265:25
  19: i_slint_core::properties::alloc_binding_holder::evaluate
             at /Users/jussi/.cargo/registry/src/index.crates.io-6f17d22bba15001f/i-slint-core-1.2.0/properties.rs:392:9
  20: i_slint_core::properties::PropertyHandle::update::{{closure}}
             at /Users/jussi/.cargo/registry/src/index.crates.io-6f17d22bba15001f/i-slint-core-1.2.0/properties.rs:576:29
  21: i_slint_core::properties::PropertyHandle::access
             at /Users/jussi/.cargo/registry/src/index.crates.io-6f17d22bba15001f/i-slint-core-1.2.0/properties.rs:481:13
  22: i_slint_core::properties::PropertyHandle::update
             at /Users/jussi/.cargo/registry/src/index.crates.io-6f17d22bba15001f/i-slint-core-1.2.0/properties.rs:571:22
  23: i_slint_core::properties::Property<T>::get
             at /Users/jussi/.cargo/registry/src/index.crates.io-6f17d22bba15001f/i-slint-core-1.2.0/properties.rs:777:18
  24: i_slint_core::items::Rectangle::background
             at /Users/jussi/.cargo/registry/src/index.crates.io-6f17d22bba15001f/i-slint-core-1.2.0/items.rs:263:33
  25: <i_slint_renderer_skia::itemrenderer::SkiaItemRenderer as i_slint_core::item_rendering::ItemRenderer>::draw_rectangle
             at /Users/jussi/.cargo/registry/src/index.crates.io-6f17d22bba15001f/i-slint-renderer-skia-1.2.0/itemrenderer.rs:297:30
  26: <i_slint_core::items::Rectangle as i_slint_core::items::Item_vtable_mod::Item>::render
             at /Users/jussi/.cargo/registry/src/index.crates.io-6f17d22bba15001f/i-slint-core-1.2.0/items.rs:335:9
  27: i_slint_core::items::RectangleVTable::render
             at /Users/jussi/.cargo/registry/src/index.crates.io-6f17d22bba15001f/i-slint-core-1.2.0/items.rs:106:1
  28: i_slint_core::items::Item_vtable_mod::ItemTO::render
             at /Users/jussi/.cargo/registry/src/index.crates.io-6f17d22bba15001f/i-slint-core-1.2.0/items.rs:106:1
  29: i_slint_core::item_rendering::render_item_children::{{closure}}
             at /Users/jussi/.cargo/registry/src/index.crates.io-6f17d22bba15001f/i-slint-core-1.2.0/item_rendering.rs:207:17
  30: i_slint_core::item_tree::<impl i_slint_core::item_tree::ItemVisitor_vtable_mod::ItemVisitor for T>::visit_item
             at /Users/jussi/.cargo/registry/src/index.crates.io-6f17d22bba15001f/i-slint-core-1.2.0/item_tree.rs:702:9
  31: i_slint_core::item_tree::ItemVisitor_vtable_mod::ItemVisitorVTable::new::visit_item
             at /Users/jussi/.cargo/registry/src/index.crates.io-6f17d22bba15001f/i-slint-core-1.2.0/item_tree.rs:673:1
  32: i_slint_core::item_tree::ItemVisitor_vtable_mod::ItemVisitorTO::visit_item
             at /Users/jussi/.cargo/registry/src/index.crates.io-6f17d22bba15001f/i-slint-core-1.2.0/item_tree.rs:673:1
  33: i_slint_core::item_tree::visit_item_tree::{{closure}}
             at /Users/jussi/.cargo/registry/src/index.crates.io-6f17d22bba15001f/i-slint-core-1.2.0/item_tree.rs:771:17
  34: i_slint_core::item_tree::visit_item_tree
             at /Users/jussi/.cargo/registry/src/index.crates.io-6f17d22bba15001f/i-slint-core-1.2.0/item_tree.rs:794:45
  35: <<convolution_plugin::plugin::ConvolutionPlugin as nih_plug::plugin::Plugin>::editor::slint_generatedHelloWorld::InnerHelloWorld as i_slint_core::component::Component_vtable_mod::Component>::visit_children_item
             at /Users/jussi/Projects/viiri/convolution-plugin/src/plugin.rs:279:9
  36: <<convolution_plugin::plugin::ConvolutionPlugin as nih_plug::plugin::Plugin>::editor::slint_generatedHelloWorld::InnerHelloWorld as const_field_offset::PinnedDrop>::drop::VT::visit_children_item
             at /Users/jussi/.cargo/registry/src/index.crates.io-6f17d22bba15001f/i-slint-core-1.2.0/component.rs:40:1
  37: i_slint_core::component::Component_vtable_mod::ComponentTO::visit_children_item
             at /Users/jussi/.cargo/registry/src/index.crates.io-6f17d22bba15001f/i-slint-core-1.2.0/component.rs:40:1
  38: i_slint_core::item_rendering::render_item_children
             at /Users/jussi/.cargo/registry/src/index.crates.io-6f17d22bba15001f/i-slint-core-1.2.0/item_rendering.rs:223:5
  39: i_slint_core::item_rendering::render_item_children::{{closure}}
             at /Users/jussi/.cargo/registry/src/index.crates.io-6f17d22bba15001f/i-slint-core-1.2.0/item_rendering.rs:217:17
  40: i_slint_core::item_tree::<impl i_slint_core::item_tree::ItemVisitor_vtable_mod::ItemVisitor for T>::visit_item
             at /Users/jussi/.cargo/registry/src/index.crates.io-6f17d22bba15001f/i-slint-core-1.2.0/item_tree.rs:702:9
  41: i_slint_core::item_tree::ItemVisitor_vtable_mod::ItemVisitorVTable::new::visit_item
             at /Users/jussi/.cargo/registry/src/index.crates.io-6f17d22bba15001f/i-slint-core-1.2.0/item_tree.rs:673:1
  42: i_slint_core::item_tree::ItemVisitor_vtable_mod::ItemVisitorTO::visit_item
             at /Users/jussi/.cargo/registry/src/index.crates.io-6f17d22bba15001f/i-slint-core-1.2.0/item_tree.rs:673:1
  43: i_slint_core::item_tree::visit_item_tree::{{closure}}
             at /Users/jussi/.cargo/registry/src/index.crates.io-6f17d22bba15001f/i-slint-core-1.2.0/item_tree.rs:771:17
  44: i_slint_core::item_tree::visit_item_tree
             at /Users/jussi/.cargo/registry/src/index.crates.io-6f17d22bba15001f/i-slint-core-1.2.0/item_tree.rs:794:45
  45: <<convolution_plugin::plugin::ConvolutionPlugin as nih_plug::plugin::Plugin>::editor::slint_generatedHelloWorld::InnerHelloWorld as i_slint_core::component::Component_vtable_mod::Component>::visit_children_item
             at /Users/jussi/Projects/viiri/convolution-plugin/src/plugin.rs:279:9
  46: <<convolution_plugin::plugin::ConvolutionPlugin as nih_plug::plugin::Plugin>::editor::slint_generatedHelloWorld::InnerHelloWorld as const_field_offset::PinnedDrop>::drop::VT::visit_children_item
             at /Users/jussi/.cargo/registry/src/index.crates.io-6f17d22bba15001f/i-slint-core-1.2.0/component.rs:40:1
  47: i_slint_core::component::Component_vtable_mod::ComponentTO::visit_children_item
             at /Users/jussi/.cargo/registry/src/index.crates.io-6f17d22bba15001f/i-slint-core-1.2.0/component.rs:40:1
  48: i_slint_core::item_rendering::render_item_children
             at /Users/jussi/.cargo/registry/src/index.crates.io-6f17d22bba15001f/i-slint-core-1.2.0/item_rendering.rs:223:5
  49: i_slint_core::item_rendering::render_item_children::{{closure}}
             at /Users/jussi/.cargo/registry/src/index.crates.io-6f17d22bba15001f/i-slint-core-1.2.0/item_rendering.rs:217:17
  50: i_slint_core::item_tree::<impl i_slint_core::item_tree::ItemVisitor_vtable_mod::ItemVisitor for T>::visit_item
             at /Users/jussi/.cargo/registry/src/index.crates.io-6f17d22bba15001f/i-slint-core-1.2.0/item_tree.rs:702:9
  51: i_slint_core::item_tree::ItemVisitor_vtable_mod::ItemVisitorVTable::new::visit_item
             at /Users/jussi/.cargo/registry/src/index.crates.io-6f17d22bba15001f/i-slint-core-1.2.0/item_tree.rs:673:1
  52: i_slint_core::item_tree::ItemVisitor_vtable_mod::ItemVisitorTO::visit_item
             at /Users/jussi/.cargo/registry/src/index.crates.io-6f17d22bba15001f/i-slint-core-1.2.0/item_tree.rs:673:1
  53: i_slint_core::item_tree::visit_item_tree::{{closure}}
             at /Users/jussi/.cargo/registry/src/index.crates.io-6f17d22bba15001f/i-slint-core-1.2.0/item_tree.rs:771:17
  54: i_slint_core::item_tree::visit_item_tree
             at /Users/jussi/.cargo/registry/src/index.crates.io-6f17d22bba15001f/i-slint-core-1.2.0/item_tree.rs:785:9
  55: <<convolution_plugin::plugin::ConvolutionPlugin as nih_plug::plugin::Plugin>::editor::slint_generatedHelloWorld::InnerHelloWorld as i_slint_core::component::Component_vtable_mod::Component>::visit_children_item
             at /Users/jussi/Projects/viiri/convolution-plugin/src/plugin.rs:279:9
  56: <<convolution_plugin::plugin::ConvolutionPlugin as nih_plug::plugin::Plugin>::editor::slint_generatedHelloWorld::InnerHelloWorld as const_field_offset::PinnedDrop>::drop::VT::visit_children_item
             at /Users/jussi/.cargo/registry/src/index.crates.io-6f17d22bba15001f/i-slint-core-1.2.0/component.rs:40:1
  57: i_slint_core::component::Component_vtable_mod::ComponentTO::visit_children_item
             at /Users/jussi/.cargo/registry/src/index.crates.io-6f17d22bba15001f/i-slint-core-1.2.0/component.rs:40:1
  58: i_slint_core::item_rendering::render_item_children
             at /Users/jussi/.cargo/registry/src/index.crates.io-6f17d22bba15001f/i-slint-core-1.2.0/item_rendering.rs:223:5
  59: i_slint_core::item_rendering::render_component_items
             at /Users/jussi/.cargo/registry/src/index.crates.io-6f17d22bba15001f/i-slint-core-1.2.0/item_rendering.rs:240:5
  60: i_slint_renderer_skia::SkiaRenderer::internal_render_with_post_callback::{{closure}}::{{closure}}
             at /Users/jussi/.cargo/registry/src/index.crates.io-6f17d22bba15001f/i-slint-renderer-skia-1.2.0/lib.rs:172:21
  61: i_slint_core::window::WindowInner::draw_contents::{{closure}}
             at /Users/jussi/.cargo/registry/src/index.crates.io-6f17d22bba15001f/i-slint-core-1.2.0/window.rs:758:17
  62: i_slint_core::properties::CURRENT_BINDING::<impl i_slint_core::properties::CURRENT_BINDING>::set
             at /Users/jussi/.cargo/registry/src/index.crates.io-6f17d22bba15001f/scoped-tls-hkt-0.1.4/src/lib.rs:265:25
  63: i_slint_core::properties::PropertyTracker<DirtyHandler>::evaluate_as_dependency_root
             at /Users/jussi/.cargo/registry/src/index.crates.io-6f17d22bba15001f/i-slint-core-1.2.0/properties.rs:1295:17
  64: i_slint_core::window::WindowInner::draw_contents
             at /Users/jussi/.cargo/registry/src/index.crates.io-6f17d22bba15001f/i-slint-core-1.2.0/window.rs:762:9
  65: i_slint_renderer_skia::SkiaRenderer::internal_render_with_post_callback::{{closure}}
             at /Users/jussi/.cargo/registry/src/index.crates.io-6f17d22bba15001f/i-slint-renderer-skia-1.2.0/lib.rs:125:13
  66: <i_slint_renderer_skia::metal_surface::MetalSurface as i_slint_renderer_skia::Surface>::render::{{closure}}
             at /Users/jussi/.cargo/registry/src/index.crates.io-6f17d22bba15001f/i-slint-renderer-skia-1.2.0/metal_surface.rs:122:13
  67: objc::rc::autorelease::autoreleasepool
             at /Users/jussi/.cargo/registry/src/index.crates.io-6f17d22bba15001f/objc-0.2.7/src/rc/autorelease.rs:29:5
  68: <i_slint_renderer_skia::metal_surface::MetalSurface as i_slint_renderer_skia::Surface>::render
             at /Users/jussi/.cargo/registry/src/index.crates.io-6f17d22bba15001f/i-slint-renderer-skia-1.2.0/metal_surface.rs:86:9
  69: i_slint_renderer_skia::SkiaRenderer::internal_render_with_post_callback
             at /Users/jussi/.cargo/registry/src/index.crates.io-6f17d22bba15001f/i-slint-renderer-skia-1.2.0/lib.rs:124:9
  70: i_slint_renderer_skia::SkiaRenderer::render
             at /Users/jussi/.cargo/registry/src/index.crates.io-6f17d22bba15001f/i-slint-renderer-skia-1.2.0/lib.rs:97:9
ilmai commented 1 year ago

FWIW this doesn't happen on Windows, where I'm using IDXGIOutput.WaitForVBlank() for vsync. On Mac I'm using CVDisplayLink.

Switching my Mac to 60Hz refresh rate doesn't help.

ogoffart commented 1 year ago

Out of curiousity, do you re-implement Platform::duration_since_start in a way that is not monotonic? Just asking if it is possible to go back in time with your platform?

ilmai commented 1 year ago

I have not reimplemented it.

ilmai commented 1 year ago

This was actually an issue with my custom platform after all. As described on Mattermost: I was calling update_timers_and_animations() from the wrong thread, and update_timers() is also called from process_mouse_input(), so time was being set alternatively to the real duration and 0. Maybe there could be a check somewhere to make it easier to catch a weird error like this?

hunger commented 1 year ago

I will close this issue now, but I opened #3491 to track making clock issues more discoverable.

ogoffart commented 1 year ago

In addition to detect non monotonic clock, we should also make sure that calling update_timers_and_animations from the wrong thread don't impact the animations in another thread.

ogoffart commented 1 year ago

I don't understand how this was actually possible, we are using thread_local storage. Calling it from the wrong thread should only update it in its thread_local variable that shouldn't be used.

Were you using the unsafe-single-threaded feature and not the std feature? (That doesn't seem possible since i can see skia in the backtrace that needs std)

ilmai commented 1 year ago

I'm using slint with "accessibility", "compat-1-2" and "std" features, with default features turned off.

ogoffart commented 10 months ago

Close this as https://github.com/slint-ui/slint/issues/3491 should take care of it

hunger commented 9 months ago

I marked this as an enhancement to stop this from showing up in the list of unlabeled issues.

tronical commented 9 months ago

I think Olivier meant to close this :)