server: Add special case destroy signal emitter

In the past much code (weston, efl/enlightenment, mutter) has
freed structures containing wl_listeners from destroy handlers
without first removing the listener from the signal.  As the
destroy notifier only fires once, this has largely gone
unnoticed until recently.

Other code does not (Qt, wlroots) - and removes itself from
the signal before free.

If somehow a destroy signal is listened to by code from both
kinds of callers, those that free will corrupt the lists for
those that don't, and Bad Things will happen.

To avoid these bad things, remove every item from the signal list
during destroy emit, and put it in a list all its own.  This way
whether the listener is removed or not has no impact on the
following emits.

Signed-off-by: Derek Foreman <derekf@osg.samsung.com>
Reviewed-by: Simon Ser <contact@emersion.fr>
Reviewed-by: Markus Ongyerth <wl@ongy.net>
This commit is contained in:
Derek Foreman 2018-04-16 15:00:59 -05:00
parent 58ee271bff
commit 5e0f7ad1bf
2 changed files with 46 additions and 3 deletions

View file

@ -253,6 +253,9 @@ wl_priv_signal_get(struct wl_priv_signal *signal, wl_notify_func_t notify);
void
wl_priv_signal_emit(struct wl_priv_signal *signal, void *data);
void
wl_priv_signal_final_emit(struct wl_priv_signal *signal, void *data);
void
wl_connection_close_fds_in(struct wl_connection *connection, int max);