wayfire
wayfire copied to clipboard
wayfire crashes when dragging waybar task icon
Describe the bug Dragging a task icon in waybar crashes wayfire
To Reproduce Enable the taskbar module and drag one of it's window icons
Edit: ALONG THE BAR
Expected behavior no crash
Screenshots or stacktrace couldn't find anything in journalctl
Wayfire version r2369.c3b1edf1-1 (Chaotic AUR)
Please compile with address sanitizer and start wayfire with its stdout/stderr redirected to a file. This way you can get a stacktrace.
Sorry, I always forget about the log - wayfire-crash.log
Is this still happening with latest master?
Latest master is crashing so early that I didn't even get any logs. I'm facing quite bad crashing issues since eaf8130. It's either crashing right after I can see something, or crashing when I open a window (autostart worked, maybe wayland windows only)
Not opening an issue for the mentioned issues because I can't get to them due to the latest crash
The stacktrace is because of ODR violations, which should be safe to ignore (although we should fix that eventually) .. try setting set ASAN_OPTIONS=detect_odr_violation=0 when starting wayfire. Also make sure to recompile all plugins not from the main repo.
what I find rather weird is that I did not get any output besides that. Usually, when wayfire crashes I can at least see some output, but that was not the case. Only what I sent above.
Edit: Weird. I deleted one of my plugins which I did not have a build script at hand and now it works again. did not expect it to be a plugin issue
Anyways, yes. I can still reproduce the issue.
Tried to reproduce the issue again on Wayfire master, but it seems to be working. As a side note, Waybar seems to crash very often, but Wayfire itself doesn't. Could you test with latest master again? And if yes, please attach a new log of the crash with address sanitizer.
well if it's working for you then I guess it's fine. I will have to mention that I have switched to Hyprland a while ago. There is a glaring issue on wayfire: You have to use the git version to be able to use wayfire-plugins-extra-git. Sadly the git version is very unstable and often crashes with some versions. Then, the wayfire-plugins-extra-git package needs to be recompiled with each update to work, but there are often compilation issues when there is a change to some api.
Thanks for your awesome work on this compositor though! It's a perfect crossover between WM and DE :)
Sadly, I managed to reproduce this issue using Wayfire commit faa5ba9c31ecb7e446709bc48848f8462af6a390 (latest as of the time this was written).
The backtrace is similar as well:
#0 0x00007ffff79dc3d3 in std::_Rb_tree_increment(std::_Rb_tree_node_base const*) () at /usr/src/debug/gcc/gcc/libstdc++-v3/src/c++98/tree.cc:89
#1 0x0000555555619319 in std::_Rb_tree_const_iterator<unsigned int>::operator++() (this=<synthetic pointer>, this=<optimized out>) at /usr/include/c++/13.2.1/bits/stl_tree.h:366
#2 wf::pointer_t::force_release_buttons() (this=this@entry=0x5555561f11c0) at ../src/core/seat/pointer.cpp:101
#3 0x00005555556194dc in wf::pointer_t::update_cursor_focus(std::shared_ptr<wf::scene::node_t>) (this=this@entry=0x5555561f11c0, new_focus=std::shared_ptr<wf::scene::node_t> (empty) = {...}) at ../src/core/seat/pointer.cpp:163
#4 0x000055555561e218 in wf::pointer_t::update_cursor_position(long, bool) (this=0x5555561f11c0, time_msec=7186919, real_update=real_update@entry=false) at ../src/core/seat/pointer.cpp:84
#5 0x000055555561e35c in wf::pointer_t::grab_surface(std::shared_ptr<wf::scene::node_t>) (node=Python Exception <class 'gdb.error'>: value has been optimized out
, this=<optimized out>) at ../src/core/seat/pointer.cpp:203
#6 0x000055555561ee16 in operator() (data=<optimized out>, __closure=<optimized out>) at ../src/core/seat/pointer.cpp:30
#7 std::__invoke_impl<void, wf::pointer_t::pointer_t(nonstd::observer_ptr<wf::input_manager_t>, nonstd::observer_ptr<wf::seat_t>)::<lambda(wf::scene::root_node_update_signal*)>&, wf::scene::root_node_update_signal*> (__f=<optimized out>) at /usr/include/c++/13.2.1/bits/invoke.h:61
#8 std::__invoke_r<void, wf::pointer_t::pointer_t(nonstd::observer_ptr<wf::input_manager_t>, nonstd::observer_ptr<wf::seat_t>)::<lambda(wf::scene::root_node_update_signal*)>&, wf::scene::root_node_update_signal*> (__fn=<optimized out>) at /usr/include/c++/13.2.1/bits/invoke.h:111
#9 std::_Function_handler<void(wf::scene::root_node_update_signal*), wf::pointer_t::pointer_t(nonstd::observer_ptr<wf::input_manager_t>, nonstd::observer_ptr<wf::seat_t>)::<lambda(wf::scene::root_node_update_signal*)> >::_M_invoke(const std::_Any_data &, wf::scene::root_node_update_signal *&&) (__functor=..., __args#0=<optimized out>) at /usr/include/c++/13.2.1/bits/std_function.h:290
#10 0x00005555555fc1e5 in std::function<void (void*)>::operator()(void*) const (__args#0=<optimized out>, this=<optimized out>) at /usr/include/c++/13.2.1/bits/std_function.h:587
#11 wf::signal::connection_t<wf::scene::root_node_update_signal>::emit(wf::scene::root_node_update_signal*) (data=<optimized out>, this=<optimized out>) at ../src/api/wayfire/signal-provider.hpp:107
#12 wf::signal::provider_t::emit<wf::scene::root_node_update_signal>(wf::scene::root_node_update_signal*)::{lambda(wf::signal::connection_base_t*)#1}::operator()(wf::signal::connection_base_t*) const (__closure=<optimized out>, tc=<optimized out>) at ../src/api/wayfire/signal-provider.hpp:163
#13 std::__invoke_impl<void, wf::signal::provider_t::emit<wf::scene::root_node_update_signal>(wf::scene::root_node_update_signal*)::{lambda(wf::signal::connection_base_t*)#1}&, wf::signal::connection_base_t*&>(std::__invoke_other, wf::signal::provider_t::emit<wf::scene::root_node_update_signal>(wf::scene::root_node_update_signal*)::{lambda(wf::signal::connection_base_t*)#1}&, wf::signal::connection_base_t*&) (__f=<optimized out>) at /usr/include/c++/13.2.1/bits/invoke.h:61
#14 std::__invoke_r<void, wf::signal::provider_t::emit<wf::scene::root_node_update_signal>(wf::scene::root_node_update_signal*)::{lambda(wf::signal::connection_base_t*)#1}&, wf::signal::connection_base_t*&>(wf::signal::provider_t::emit<wf::scene::root_node_update_signal>(wf::scene::root_node_update_signal*)::{lambda(wf::signal::connection_base_t*)#1}&, wf::signal::connection_base_t*&) (__fn=<optimized out>) at /usr/include/c++/13.2.1/bits/invoke.h:111
#15 std::_Function_handler<void (wf::signal::connection_base_t*&), wf::signal::provider_t::emit<wf::scene::root_node_update_signal>(wf::scene::root_node_update_signal*)::{lambda(wf::signal::connection_base_t*)#1}>::_M_invoke(std::_Any_data const&, wf::signal::connection_base_t*&) (__functor=<optimized out>, __args#0=<optimized out>) at /usr/include/c++/13.2.1/bits/std_function.h:290
#16 0x00005555555dabb5 in std::function<void (wf::signal::connection_base_t*&)>::operator()(wf::signal::connection_base_t*&) const (__args#0=<optimized out>, this=0x7fffffffdb00) at /usr/include/c++/13.2.1/bits/std_function.h:591
#17 wf::safe_list_t<wf::signal::connection_base_t*>::for_each(std::function<void (wf::signal::connection_base_t*&)>) (this=0x5555562a3cf0, func=...) at ../src/api/wayfire/nonstd/safe-list.hpp:78
#18 0x00005555555fdd4f in wf::signal::provider_t::emit<wf::scene::root_node_update_signal>(wf::scene::root_node_update_signal*) (data=<optimized out>, this=<optimized out>) at ../src/api/wayfire/signal-provider.hpp:159
#19 wf::scene::update(std::shared_ptr<wf::scene::node_t>, unsigned int) (changed_node=std::shared_ptr<wf::scene::node_t> (use count 2, weak count 1) = {...}, flags=<optimized out>) at ../src/core/scene.cpp:499
#20 0x00005555555fdc88 in wf::scene::update(std::shared_ptr<wf::scene::node_t>, unsigned int) (changed_node=std::shared_ptr<wf::scene::node_t> (use count 3, weak count 1) = {...}, flags=5) at ../src/core/scene.cpp:505
#21 0x00005555555fdc88 in wf::scene::update(std::shared_ptr<wf::scene::node_t>, unsigned int) (changed_node=std::shared_ptr<wf::scene::node_t> (use count 3, weak count 1) = {...}, flags=5) at ../src/core/scene.cpp:505
#22 0x00005555555fdc88 in wf::scene::update(std::shared_ptr<wf::scene::node_t>, unsigned int) (changed_node=std::shared_ptr<wf::scene::node_t> (use count 3, weak count 1) = {...}, flags=5) at ../src/core/scene.cpp:505
#23 0x00005555555fdc88 in wf::scene::update(std::shared_ptr<wf::scene::node_t>, unsigned int) (changed_node=std::shared_ptr<wf::scene::node_t> (use count 3, weak count 1) = {...}, flags=5) at ../src/core/scene.cpp:505
#24 0x00005555555fdc88 in wf::scene::update(std::shared_ptr<wf::scene::node_t>, unsigned int) (changed_node=std::shared_ptr<wf::scene::node_t> (use count 6, weak count 1) = {...}, flags=5) at ../src/core/scene.cpp:505
#25 0x0000555555636896 in replace_node_or_add_front(wf::scene::floating_inner_ptr, wf::scene::node_ptr, wf::scene::node_ptr) (surface_root_node=std::shared_ptr<wf::scene::floating_inner_node_t> (use count 6, weak count 1) = {...}, node_in_list=std::shared_ptr<wf::scene::node_t> (use count 3, weak count 1) = {...}, new_node=std::shared_ptr<wf::scene::node_t> (use count 4, weak count 1) = {...}) at ../src/view/view-impl.cpp:205
#26 0x0000555555636c78 in wf::view_interface_t::view_priv_impl::unset_mapped_surface_contents() (this=0x555556586900) at ../src/view/view-impl.cpp:233
#27 0x0000555555651889 in wayfire_layer_shell_view::unmap() (this=0x5555563ce8a0) at /usr/include/c++/13.2.1/bits/unique_ptr.h:199
#28 0x00005555555d354a in std::function<void (void*)>::operator()(void*) const (__args#0=<optimized out>, this=<optimized out>) at /usr/include/c++/13.2.1/bits/std_function.h:591
#29 wf::wl_listener_wrapper::emit(void*) (data=<optimized out>, this=<optimized out>) at ../src/wl-listener-wrapper.tpp:57
#30 wf::handle_wrapped_listener(wl_listener*, void*) (listener=<optimized out>, data=<optimized out>) at ../src/wl-listener-wrapper.tpp:10
#31 0x00007ffff7f0601e in wl_signal_emit_mutable (signal=signal@entry=0x555556605680, data=data@entry=0x5555566055a0) at ../wayland-1.22.0/src/wayland-server.c:2241
#32 0x00007ffff7e88705 in layer_surface_unmap (surface=surface@entry=0x5555566055a0) at ../wlroots-hidpi-xprop-git/types/wlr_layer_shell_v1.c:269
#33 0x00007ffff7e88818 in layer_surface_role_destroy (wlr_surface=<optimized out>) at ../wlroots-hidpi-xprop-git/types/wlr_layer_shell_v1.c:384
#34 0x00007ffff7e7c340 in wlr_surface_destroy_role_object (surface=surface@entry=0x5555569214a0) at ../wlroots-hidpi-xprop-git/types/wlr_compositor.c:733
#35 0x00007ffff7e80a86 in surface_handle_resource_destroy (resource=<optimized out>) at ../wlroots-hidpi-xprop-git/types/wlr_compositor.c:616
#36 0x00007ffff7f079ba in destroy_resource (element=0x555556921800, data=data@entry=0x7fffffffdfb4, flags=0) at ../wayland-1.22.0/src/wayland-server.c:732
#37 0x00007ffff7f080db in for_each_helper (entries=0x5555566110d0, data=0x7fffffffdfb4, func=0x7ffff7f07900 <destroy_resource>) at ../wayland-1.22.0/src/wayland-util.c:416
#38 wl_map_for_each (data=0x7fffffffdfb4, func=0x7ffff7f07900 <destroy_resource>, map=0x5555566110d0) at ../wayland-1.22.0/src/wayland-util.c:430
#39 wl_client_destroy (client=0x5555566110a0) at ../wayland-1.22.0/src/wayland-server.c:928
#40 0x00007ffff7f0860e in destroy_client_with_error (reason=<optimized out>, client=<optimized out>) at ../wayland-1.22.0/src/wayland-server.c:325
#41 wl_client_connection_data (fd=<optimized out>, mask=<optimized out>, data=<optimized out>) at ../wayland-1.22.0/src/wayland-server.c:454
#42 0x00007ffff7f07ae2 in wl_event_loop_dispatch (loop=0x5555556f9230, timeout=timeout@entry=-1) at ../wayland-1.22.0/src/event-loop.c:1027
#43 0x00007ffff7f082d7 in wl_display_run (display=0x5555556f9140) at ../wayland-1.22.0/src/wayland-server.c:1493
#44 0x00005555555d1db1 in main(int, char**) (argc=<optimized out>, argv=<optimized out>) at ../src/main.cpp:417
@tildearrow if you can reproduce easily, would you mind sharing the full wayfire log if you run with -d -d pointer?
Sure! here.log
I've also attempted to debug using Valgrind, and found something interesting. Here's the error reported by Valgrind when it crashes: valgrind.log
Using Valgrind made it a lot more difficult to reproduce, but it did reproduce.
Yeah, wait. Why is it changing the cursor focus twice?
It appears I found a possible recursion!
After adding a mutex to wf::pointer_t::update_cursor_position() (just in case this could have been a threading problem), Wayfire stopped crashing, but instead it deadlocked. The resulting backtrace is interesting: recursion.log
wf::pointer_t::update_cursor_position calls wf::pointer_t::update_cursor_focus, which calls wf::pointer_t::force_release_buttons, which calls wf::wlr_surface_pointer_interaction_t::handle_pointer_button, which somehow emits a signal and calls wf::pointer_t::update_cursor_position again....
Wayfire is not multi-threaded which is why a mutex is unlikely to be the solution here ... But I do find the double force-release message dubious. I would suggest adding a wf::print_trace(false) call when the message is printed (maybe add a static bool flag to check for when the second recursive call happens) to see how the full recursive backtrace looks like
maybe add a static bool flag to check for when the second recursive call happens
This sounds like a good idea, or a flag in pointer_t. Will work on it tomorrow.
Update: After adding a recursion check to update_cursor_focus, the crash is fixed! Now it's just waybar that crashes, but I am hoping this is a waybar bug...
.........sadly, waybar doesn't seem to crash on Sway. I'll run Valgrind once more, but here's a preliminary patch which fixes the Wayfire crash: fix-1635.txt
(apparently I am not able to upload .patch files...)
waybar also crashes under labwc!
Gdk-Message: 23:24:53.386: Error 22 (Invalid argument) dispatching to Wayland display.
Then it closes.
Confirming that the waybar crash is a waybar issue (https://github.com/Alexays/Waybar/issues/1866).
Could you use wf::print_trace in the recursive case so that we can see how it happens exactly and fix it "properly"?
Here it is: wayfire.log
So it is as I suspected might be the case .. I'll think of the correct way to fix the problem, thanks for the investigation so far :)