wayfire icon indicating copy to clipboard operation
wayfire copied to clipboard

wayfire crashes when dragging waybar task icon

Open UltraBlackLinux opened this issue 2 years ago • 20 comments

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)

UltraBlackLinux avatar Nov 26 '22 12:11 UltraBlackLinux

Please compile with address sanitizer and start wayfire with its stdout/stderr redirected to a file. This way you can get a stacktrace.

ammen99 avatar Nov 30 '22 08:11 ammen99

Sorry, I always forget about the log - wayfire-crash.log

UltraBlackLinux avatar Nov 30 '22 19:11 UltraBlackLinux

Is this still happening with latest master?

ammen99 avatar Jan 04 '23 08:01 ammen99

wayfire.log

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

UltraBlackLinux avatar Jan 04 '23 09:01 UltraBlackLinux

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.

ammen99 avatar Jan 04 '23 09:01 ammen99

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

UltraBlackLinux avatar Jan 04 '23 09:01 UltraBlackLinux

Anyways, yes. I can still reproduce the issue.

UltraBlackLinux avatar Jan 04 '23 09:01 UltraBlackLinux

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.

ammen99 avatar Jul 30 '23 14:07 ammen99

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 :)

UltraBlackLinux avatar Jul 30 '23 16:07 UltraBlackLinux

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 avatar Oct 15 '23 08:10 tildearrow

@tildearrow if you can reproduce easily, would you mind sharing the full wayfire log if you run with -d -d pointer?

ammen99 avatar Oct 15 '23 08:10 ammen99

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?

tildearrow avatar Oct 15 '23 09:10 tildearrow

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....

tildearrow avatar Oct 15 '23 09:10 tildearrow

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

ammen99 avatar Oct 15 '23 10:10 ammen99

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.

tildearrow avatar Oct 15 '23 10:10 tildearrow

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...)

tildearrow avatar Oct 16 '23 04:10 tildearrow

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).

tildearrow avatar Oct 16 '23 04:10 tildearrow

Could you use wf::print_trace in the recursive case so that we can see how it happens exactly and fix it "properly"?

ammen99 avatar Oct 16 '23 06:10 ammen99

Here it is: wayfire.log

tildearrow avatar Oct 16 '23 07:10 tildearrow

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 :)

ammen99 avatar Oct 16 '23 08:10 ammen99