server: add a safer signal type and port wl_display to it

wl_list_for_each_safe, which is used by wl_signal_emit is not really
safe. If a signal has two listeners, and the first one removes and
re-inits the second one, it would enter an infinite loop, which was hit
in weston on resource destruction, which emits a signal.
This commit adds a new version of wl_signal, called wl_priv_signal,
which is private in wayland-server.c and which does not have this problem.
The old wl_signal cannot be improved without breaking backwards compatibility.

Signed-off-by: Giulio Camuffo <giulio.camuffo@kdab.com>
Reviewed-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>
This commit is contained in:
Giulio Camuffo 2017-01-24 16:34:28 +02:00 committed by Pekka Paalanen
parent 23d8bc5a64
commit 5e6eb03229
4 changed files with 459 additions and 9 deletions

View file

@ -35,6 +35,7 @@
#define WL_HIDE_DEPRECATED 1
#include "wayland-util.h"
#include "wayland-server-core.h"
/* Invalid memory address */
#define WL_ARRAY_POISON_PTR (void *) 4
@ -233,4 +234,21 @@ zalloc(size_t s)
return calloc(1, s);
}
struct wl_priv_signal {
struct wl_list listener_list;
struct wl_list emit_list;
};
void
wl_priv_signal_init(struct wl_priv_signal *signal);
void
wl_priv_signal_add(struct wl_priv_signal *signal, struct wl_listener *listener);
struct wl_listener *
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);
#endif