[PATCH wayland v3 3/3] server: use the new wl_priv_signal for wl_resource
Giulio Camuffo
giuliocamuffo at gmail.com
Tue Jan 24 14:34:30 UTC 2017
The old wl_signal is kept for backwards compatibility, as that is also
present in the deprecated public wl_resource struct, and that must be
kept working.
---
src/wayland-server.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++------
1 file changed, 46 insertions(+), 6 deletions(-)
diff --git a/src/wayland-server.c b/src/wayland-server.c
index 86fa025..49ce7b1 100644
--- a/src/wayland-server.c
+++ b/src/wayland-server.c
@@ -117,11 +117,16 @@ struct wl_resource {
struct wl_object object;
wl_resource_destroy_func_t destroy;
struct wl_list link;
- struct wl_signal destroy_signal;
+ /* Unfortunately some users of libwayland (e.g. mesa) still use the
+ * deprecated wl_resource struct, even if creating it with the new
+ * wl_resource_create(). So we cannot change the layout of the struct
+ * unless after the data field. */
+ struct wl_signal deprecated_destroy_signal;
struct wl_client *client;
void *data;
int version;
wl_dispatcher_func_t dispatcher;
+ struct wl_priv_signal destroy_signal;
};
struct wl_protocol_logger {
@@ -597,6 +602,31 @@ wl_resource_post_no_memory(struct wl_resource *resource)
WL_DISPLAY_ERROR_NO_MEMORY, "no memory");
}
+/** Detect if a wl_resource uses the deprecated public definition.
+ *
+ * Before Wayland 1.2.0, the definition of struct wl_resource was public.
+ * It was made opaque just before 1.2.0, and later new fields were added.
+ * The new fields cannot be accessed if a program is using the deprecated
+ * defition, as there would not be memory allocated for them.
+ *
+ * The creation pattern for the deprecated definition was wl_resource_init()
+ * followed by wl_client_add_resource(). wl_resource_init() was an inline
+ * function and no longer exists, but binaries might still carry it.
+ * wl_client_add_resource() still exists for ABI compatiblity.
+ */
+static bool
+resource_is_deprecated(struct wl_resource *resource)
+{
+ struct wl_map *map = &resource->client->objects;
+ int id = resource->object.id;
+
+ /* wl_client_add_resource() marks deprecated resources with the flag. */
+ if (wl_map_lookup_flags(map, id) & WL_MAP_ENTRY_LEGACY)
+ return true;
+
+ return false;
+}
+
static enum wl_iterator_result
destroy_resource(void *element, void *data)
{
@@ -604,7 +634,11 @@ destroy_resource(void *element, void *data)
struct wl_client *client = resource->client;
uint32_t flags;
- wl_signal_emit(&resource->destroy_signal, resource);
+ wl_signal_emit(&resource->deprecated_destroy_signal, resource);
+ /* Don't emit the new signal for deprecated resources, as that would
+ * access memory outside the bounds of the deprecated struct */
+ if (!resource_is_deprecated(resource))
+ wl_priv_signal_emit(&resource->destroy_signal, resource);
flags = wl_map_lookup_flags(&client->objects, resource->object.id);
if (resource->destroy)
@@ -716,14 +750,19 @@ WL_EXPORT void
wl_resource_add_destroy_listener(struct wl_resource *resource,
struct wl_listener * listener)
{
- wl_signal_add(&resource->destroy_signal, listener);
+ if (resource_is_deprecated(resource))
+ wl_signal_add(&resource->deprecated_destroy_signal, listener);
+ else
+ wl_priv_signal_add(&resource->destroy_signal, listener);
}
WL_EXPORT struct wl_listener *
wl_resource_get_destroy_listener(struct wl_resource *resource,
wl_notify_func_t notify)
{
- return wl_signal_get(&resource->destroy_signal, notify);
+ if (resource_is_deprecated(resource))
+ return wl_signal_get(&resource->deprecated_destroy_signal, notify);
+ return wl_priv_signal_get(&resource->destroy_signal, notify);
}
/** Retrieve the interface name (class) of a resource object.
@@ -1490,7 +1529,8 @@ wl_resource_create(struct wl_client *client,
resource->object.interface = interface;
resource->object.implementation = NULL;
- wl_signal_init(&resource->destroy_signal);
+ wl_signal_init(&resource->deprecated_destroy_signal);
+ wl_priv_signal_init(&resource->destroy_signal);
resource->destroy = NULL;
resource->client = client;
@@ -1858,7 +1898,7 @@ wl_client_add_resource(struct wl_client *client,
}
resource->client = client;
- wl_signal_init(&resource->destroy_signal);
+ wl_signal_init(&resource->deprecated_destroy_signal);
return resource->object.id;
}
--
2.11.0
More information about the wayland-devel
mailing list