Segfault in desktop-shell when focused client shuts down abruptly
Under certain conditions, when a focused client is shut down abruptly weston/desktop-shell crashes.
This is the result of a signal listener being removed from within the invocation of the previous listener in the listener list. wl_signal_emit uses wl_list_for_each_safe() but this is safe only for removal of the currently invoked listener.
In this particular case, when emitting the destroy_signal for a surface, the focus_state->surface_destroy_listener
is notified first and down the line calls weston_keyboard_set_focus() which removes the seat->saved_kbd_focus_listener
. The saved_kbd_focus_listener happens to be the next listener in the surface's destroy_signal listener list, wreaking havoc on the listener iteration.
To reproduce:
- Start weston with desktop-shell with X11 backend
- Start a weston client A (e.g., weston-terminal)
- Start a second weston client B from an X11 terminal (e.g., another weston-terminal)
- Click on client B's window
- Ctrl-C client B
Result:
Thread 1 "weston" received signal SIGSEGV, Segmentation fault.
0x00007ffff7d76615 in wl_signal_emit (signal=0x555555c8adc8, data=0x555555c8adc0)
at /usr/include/wayland-server-core.h:477
477 wl_list_for_each_safe(l, next, &signal->listener_list, link)
(gdb) bt
#0 0x00007ffff7d76615 in wl_signal_emit (signal=0x555555c8adc8, data=0x555555c8adc0)
at /usr/include/wayland-server-core.h:477
#1 0x00007ffff7d7b76d in weston_surface_destroy (surface=0x555555c8adc0)
at ../libweston/compositor.c:2220
#2 0x00007fffeefee60e in fade_out_done_idle_cb (data=0x555555591440) at ../desktop-shell/shell.c:2335
#3 0x00007ffff7d4731b in wl_event_loop_dispatch_idle (loop=loop@entry=0x555555562f00)
at ../src/event-loop.c:969
#4 0x00007ffff7d47422 in wl_event_loop_dispatch (loop=0x555555562f00, timeout=timeout@entry=-1)
at ../src/event-loop.c:1032
#5 0x00007ffff7d459e5 in wl_display_run (display=0x555555568fd0) at ../src/wayland-server.c:1351
#6 0x00007ffff7fbd47f in wet_main (argc=1, argv=0x7fffffffd938) at ../compositor/main.c:3398
#7 0x0000555555555155 in main (argc=6, argv=0x7fffffffd938) at ../compositor/executable.c:33