|
|
f7d48e |
From 5e4a1290ce75ed94e3f0f457d35a225f2ef3878c Mon Sep 17 00:00:00 2001
|
|
|
f7d48e |
From: Olivier Fourdan <ofourdan@redhat.com>
|
|
|
f7d48e |
Date: Tue, 28 Nov 2017 10:54:08 +0100
|
|
|
f7d48e |
Subject: [PATCH] wayland: Avoid a race in wl_seat capabilities
|
|
|
f7d48e |
|
|
|
f7d48e |
The way wl_seat capabilities work, by notifying clients of capabilities
|
|
|
f7d48e |
changes, and clients consequently requesting the relevant interface
|
|
|
f7d48e |
objects (pointer, keyboard, touch) is inherently racy.
|
|
|
f7d48e |
|
|
|
f7d48e |
On quick VT changes for example, capabilities on the seat will be added
|
|
|
f7d48e |
and removed, and by the time the client receives the capability change
|
|
|
f7d48e |
notification and requests the relevant keyboard, pointer or touch,
|
|
|
f7d48e |
another VT switch might have occurred and the wl_pointer, wl_keyboard or
|
|
|
f7d48e |
wl_touch already destroyed, leading to a protocol error which kills the
|
|
|
f7d48e |
client.
|
|
|
f7d48e |
|
|
|
f7d48e |
To avoid this, create the objects when requested regardless of the
|
|
|
f7d48e |
capabilities.
|
|
|
f7d48e |
|
|
|
f7d48e |
Closes: https://gitlab.gnome.org/GNOME/mutter/-/issues/1797
|
|
|
f7d48e |
Related: https://bugzilla.gnome.org/show_bug.cgi?id=790932
|
|
|
f7d48e |
---
|
|
|
f7d48e |
src/wayland/meta-wayland-pointer.c | 45 ++++++++++++++++++++++++------
|
|
|
f7d48e |
src/wayland/meta-wayland-seat.c | 9 ++----
|
|
|
f7d48e |
src/wayland/meta-wayland-touch.c | 8 ------
|
|
|
f7d48e |
3 files changed, 40 insertions(+), 22 deletions(-)
|
|
|
f7d48e |
|
|
|
f7d48e |
diff --git a/src/wayland/meta-wayland-pointer.c b/src/wayland/meta-wayland-pointer.c
|
|
|
f7d48e |
index 3132abfd2..abd779ad7 100644
|
|
|
f7d48e |
--- a/src/wayland/meta-wayland-pointer.c
|
|
|
f7d48e |
+++ b/src/wayland/meta-wayland-pointer.c
|
|
|
f7d48e |
@@ -109,7 +109,7 @@ meta_wayland_pointer_client_new (void)
|
|
|
f7d48e |
}
|
|
|
f7d48e |
|
|
|
f7d48e |
static void
|
|
|
f7d48e |
-meta_wayland_pointer_client_free (MetaWaylandPointerClient *pointer_client)
|
|
|
f7d48e |
+meta_wayland_pointer_make_resources_inert (MetaWaylandPointerClient *pointer_client)
|
|
|
f7d48e |
{
|
|
|
f7d48e |
struct wl_resource *resource, *next;
|
|
|
f7d48e |
|
|
|
f7d48e |
@@ -141,10 +141,25 @@ meta_wayland_pointer_client_free (MetaWaylandPointerClient *pointer_client)
|
|
|
f7d48e |
wl_list_init (wl_resource_get_link (resource));
|
|
|
f7d48e |
wl_resource_set_user_data (resource, NULL);
|
|
|
f7d48e |
}
|
|
|
f7d48e |
+}
|
|
|
f7d48e |
|
|
|
f7d48e |
+static void
|
|
|
f7d48e |
+meta_wayland_pointer_client_free (MetaWaylandPointerClient *pointer_client)
|
|
|
f7d48e |
+{
|
|
|
f7d48e |
+ meta_wayland_pointer_make_resources_inert (pointer_client);
|
|
|
f7d48e |
g_free (pointer_client);
|
|
|
f7d48e |
}
|
|
|
f7d48e |
|
|
|
f7d48e |
+static void
|
|
|
f7d48e |
+make_resources_inert_foreach (gpointer key,
|
|
|
f7d48e |
+ gpointer value,
|
|
|
f7d48e |
+ gpointer data)
|
|
|
f7d48e |
+{
|
|
|
f7d48e |
+ MetaWaylandPointerClient *pointer_client = value;
|
|
|
f7d48e |
+
|
|
|
f7d48e |
+ meta_wayland_pointer_make_resources_inert (pointer_client);
|
|
|
f7d48e |
+}
|
|
|
f7d48e |
+
|
|
|
f7d48e |
static gboolean
|
|
|
f7d48e |
meta_wayland_pointer_client_is_empty (MetaWaylandPointerClient *pointer_client)
|
|
|
f7d48e |
{
|
|
|
f7d48e |
@@ -158,8 +173,6 @@ MetaWaylandPointerClient *
|
|
|
f7d48e |
meta_wayland_pointer_get_pointer_client (MetaWaylandPointer *pointer,
|
|
|
f7d48e |
struct wl_client *client)
|
|
|
f7d48e |
{
|
|
|
f7d48e |
- if (!pointer->pointer_clients)
|
|
|
f7d48e |
- return NULL;
|
|
|
f7d48e |
return g_hash_table_lookup (pointer->pointer_clients, client);
|
|
|
f7d48e |
}
|
|
|
f7d48e |
|
|
|
f7d48e |
@@ -475,10 +488,6 @@ meta_wayland_pointer_enable (MetaWaylandPointer *pointer)
|
|
|
f7d48e |
MetaCursorTracker *cursor_tracker = meta_backend_get_cursor_tracker (backend);
|
|
|
f7d48e |
ClutterSeat *clutter_seat;
|
|
|
f7d48e |
|
|
|
f7d48e |
- pointer->pointer_clients =
|
|
|
f7d48e |
- g_hash_table_new_full (NULL, NULL, NULL,
|
|
|
f7d48e |
- (GDestroyNotify) meta_wayland_pointer_client_free);
|
|
|
f7d48e |
-
|
|
|
f7d48e |
pointer->cursor_surface = NULL;
|
|
|
f7d48e |
|
|
|
f7d48e |
clutter_seat = clutter_backend_get_default_seat (clutter_get_default_backend ());
|
|
|
f7d48e |
@@ -508,6 +517,10 @@ meta_wayland_pointer_disable (MetaWaylandPointer *pointer)
|
|
|
f7d48e |
ClutterBackend *clutter_backend = clutter_get_default_backend ();
|
|
|
f7d48e |
ClutterSeat *clutter_seat = clutter_backend_get_default_seat (clutter_backend);
|
|
|
f7d48e |
|
|
|
f7d48e |
+ g_hash_table_foreach (pointer->pointer_clients,
|
|
|
f7d48e |
+ make_resources_inert_foreach,
|
|
|
f7d48e |
+ NULL);
|
|
|
f7d48e |
+
|
|
|
f7d48e |
g_signal_handlers_disconnect_by_func (cursor_tracker,
|
|
|
f7d48e |
(gpointer) meta_wayland_pointer_on_cursor_changed,
|
|
|
f7d48e |
pointer);
|
|
|
f7d48e |
@@ -531,7 +544,6 @@ meta_wayland_pointer_disable (MetaWaylandPointer *pointer)
|
|
|
f7d48e |
meta_wayland_pointer_set_focus (pointer, NULL);
|
|
|
f7d48e |
meta_wayland_pointer_set_current (pointer, NULL);
|
|
|
f7d48e |
|
|
|
f7d48e |
- g_clear_pointer (&pointer->pointer_clients, g_hash_table_unref);
|
|
|
f7d48e |
pointer->cursor_surface = NULL;
|
|
|
f7d48e |
}
|
|
|
f7d48e |
|
|
|
f7d48e |
@@ -1356,11 +1368,28 @@ meta_wayland_pointer_init (MetaWaylandPointer *pointer)
|
|
|
f7d48e |
pointer->default_grab.interface = &default_pointer_grab_interface;
|
|
|
f7d48e |
pointer->default_grab.pointer = pointer;
|
|
|
f7d48e |
pointer->grab = &pointer->default_grab;
|
|
|
f7d48e |
+ pointer->pointer_clients =
|
|
|
f7d48e |
+ g_hash_table_new_full (NULL, NULL, NULL,
|
|
|
f7d48e |
+ (GDestroyNotify) meta_wayland_pointer_client_free);
|
|
|
f7d48e |
+}
|
|
|
f7d48e |
+
|
|
|
f7d48e |
+static void
|
|
|
f7d48e |
+meta_wayland_pointer_finalize (GObject *object)
|
|
|
f7d48e |
+{
|
|
|
f7d48e |
+ MetaWaylandPointer *pointer = META_WAYLAND_POINTER (object);
|
|
|
f7d48e |
+
|
|
|
f7d48e |
+ g_clear_pointer (&pointer->pointer_clients, g_hash_table_unref);
|
|
|
f7d48e |
+
|
|
|
f7d48e |
+ G_OBJECT_CLASS (meta_wayland_pointer_parent_class)->finalize (object);
|
|
|
f7d48e |
}
|
|
|
f7d48e |
|
|
|
f7d48e |
static void
|
|
|
f7d48e |
meta_wayland_pointer_class_init (MetaWaylandPointerClass *klass)
|
|
|
f7d48e |
{
|
|
|
f7d48e |
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
|
|
f7d48e |
+
|
|
|
f7d48e |
+ object_class->finalize = meta_wayland_pointer_finalize;
|
|
|
f7d48e |
+
|
|
|
f7d48e |
signals[FOCUS_SURFACE_CHANGED] = g_signal_new ("focus-surface-changed",
|
|
|
f7d48e |
G_TYPE_FROM_CLASS (klass),
|
|
|
f7d48e |
G_SIGNAL_RUN_LAST,
|
|
|
f7d48e |
diff --git a/src/wayland/meta-wayland-seat.c b/src/wayland/meta-wayland-seat.c
|
|
|
f7d48e |
index c6390dde7..efce6d6d6 100644
|
|
|
f7d48e |
--- a/src/wayland/meta-wayland-seat.c
|
|
|
f7d48e |
+++ b/src/wayland/meta-wayland-seat.c
|
|
|
f7d48e |
@@ -46,8 +46,7 @@ seat_get_pointer (struct wl_client *client,
|
|
|
f7d48e |
MetaWaylandSeat *seat = wl_resource_get_user_data (resource);
|
|
|
f7d48e |
MetaWaylandPointer *pointer = seat->pointer;
|
|
|
f7d48e |
|
|
|
f7d48e |
- if (meta_wayland_seat_has_pointer (seat))
|
|
|
f7d48e |
- meta_wayland_pointer_create_new_resource (pointer, client, resource, id);
|
|
|
f7d48e |
+ meta_wayland_pointer_create_new_resource (pointer, client, resource, id);
|
|
|
f7d48e |
}
|
|
|
f7d48e |
|
|
|
f7d48e |
static void
|
|
|
f7d48e |
@@ -58,8 +57,7 @@ seat_get_keyboard (struct wl_client *client,
|
|
|
f7d48e |
MetaWaylandSeat *seat = wl_resource_get_user_data (resource);
|
|
|
f7d48e |
MetaWaylandKeyboard *keyboard = seat->keyboard;
|
|
|
f7d48e |
|
|
|
f7d48e |
- if (meta_wayland_seat_has_keyboard (seat))
|
|
|
f7d48e |
- meta_wayland_keyboard_create_new_resource (keyboard, client, resource, id);
|
|
|
f7d48e |
+ meta_wayland_keyboard_create_new_resource (keyboard, client, resource, id);
|
|
|
f7d48e |
}
|
|
|
f7d48e |
|
|
|
f7d48e |
static void
|
|
|
f7d48e |
@@ -70,8 +68,7 @@ seat_get_touch (struct wl_client *client,
|
|
|
f7d48e |
MetaWaylandSeat *seat = wl_resource_get_user_data (resource);
|
|
|
f7d48e |
MetaWaylandTouch *touch = seat->touch;
|
|
|
f7d48e |
|
|
|
f7d48e |
- if (meta_wayland_seat_has_touch (seat))
|
|
|
f7d48e |
- meta_wayland_touch_create_new_resource (touch, client, resource, id);
|
|
|
f7d48e |
+ meta_wayland_touch_create_new_resource (touch, client, resource, id);
|
|
|
f7d48e |
}
|
|
|
f7d48e |
|
|
|
f7d48e |
static void
|
|
|
f7d48e |
diff --git a/src/wayland/meta-wayland-touch.c b/src/wayland/meta-wayland-touch.c
|
|
|
f7d48e |
index 002ff16f7..15f0312eb 100644
|
|
|
f7d48e |
--- a/src/wayland/meta-wayland-touch.c
|
|
|
f7d48e |
+++ b/src/wayland/meta-wayland-touch.c
|
|
|
f7d48e |
@@ -521,16 +521,8 @@ meta_wayland_touch_create_new_resource (MetaWaylandTouch *touch,
|
|
|
f7d48e |
struct wl_resource *seat_resource,
|
|
|
f7d48e |
uint32_t id)
|
|
|
f7d48e |
{
|
|
|
f7d48e |
- MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource);
|
|
|
f7d48e |
struct wl_resource *cr;
|
|
|
f7d48e |
|
|
|
f7d48e |
- if (!meta_wayland_seat_has_touch (seat))
|
|
|
f7d48e |
- {
|
|
|
f7d48e |
- wl_resource_post_error (seat_resource, WL_DISPLAY_ERROR_INVALID_METHOD,
|
|
|
f7d48e |
- "Cannot retrieve touch interface without touch capability");
|
|
|
f7d48e |
- return;
|
|
|
f7d48e |
- }
|
|
|
f7d48e |
-
|
|
|
f7d48e |
cr = wl_resource_create (client, &wl_touch_interface, wl_resource_get_version (seat_resource), id);
|
|
|
f7d48e |
wl_resource_set_implementation (cr, &touch_interface, touch, unbind_resource);
|
|
|
f7d48e |
wl_list_insert (&touch->resource_list, wl_resource_get_link (cr));
|
|
|
f7d48e |
--
|
|
|
f7d48e |
2.31.1
|
|
|
f7d48e |
|