wayland: Nullify monitor resources when updating outputs

If a client asks for xdg-output before we have set the output's logical
monitor, we would end up crashing with a NULL pointer dereference.

Make sure we clear the resource's user data when marking an output as
inert on monitor change so that we don't end up with a Wayland output
without a logical monitor.

Closes: https://gitlab.gnome.org/GNOME/mutter/issues/194


(cherry picked from commit 48eaa36d41)
This commit is contained in:
Olivier Fourdan 2018-07-27 16:32:31 +00:00 committed by Marco Trevisan
parent 007864ac64
commit f45af3315d

View File

@ -365,12 +365,38 @@ meta_wayland_output_new (MetaWaylandCompositor *compositor,
} }
static void static void
nullify_logical_monitor (gpointer key, make_output_resources_inert (MetaWaylandOutput *wayland_output)
gpointer value, {
gpointer data) GList *l;
for (l = wayland_output->resources; l; l = l->next)
{
struct wl_resource *output_resource = l->data;
wl_resource_set_user_data (output_resource, NULL);
}
g_list_free (wayland_output->resources);
wayland_output->resources = NULL;
for (l = wayland_output->xdg_output_resources; l; l = l->next)
{
struct wl_resource *xdg_output_resource = l->data;
wl_resource_set_user_data (xdg_output_resource, NULL);
}
g_list_free (wayland_output->xdg_output_resources);
wayland_output->xdg_output_resources = NULL;
}
static void
make_output_inert (gpointer key,
gpointer value,
gpointer data)
{ {
MetaWaylandOutput *wayland_output = value; MetaWaylandOutput *wayland_output = value;
wayland_output->logical_monitor = NULL; wayland_output->logical_monitor = NULL;
make_output_resources_inert (wayland_output);
} }
static gboolean static gboolean
@ -420,7 +446,7 @@ meta_wayland_compositor_update_outputs (MetaWaylandCompositor *compositor,
wayland_output); wayland_output);
} }
g_hash_table_foreach (compositor->outputs, nullify_logical_monitor, NULL); g_hash_table_foreach (compositor->outputs, make_output_inert, NULL);
g_timeout_add_seconds (10, delayed_destroy_outputs, compositor->outputs); g_timeout_add_seconds (10, delayed_destroy_outputs, compositor->outputs);
return new_table; return new_table;
@ -449,23 +475,7 @@ meta_wayland_output_finalize (GObject *object)
/* Make sure the wl_output destructor doesn't try to access MetaWaylandOutput /* Make sure the wl_output destructor doesn't try to access MetaWaylandOutput
* after we have freed it. * after we have freed it.
*/ */
for (l = wayland_output->resources; l; l = l->next) make_output_resources_inert (wayland_output);
{
struct wl_resource *output_resource = l->data;
wl_resource_set_user_data (output_resource, NULL);
}
g_list_free (wayland_output->resources);
for (l = wayland_output->xdg_output_resources; l; l = l->next)
{
struct wl_resource *xdg_output_resource = l->data;
wl_resource_set_user_data (xdg_output_resource, NULL);
}
g_list_free (wayland_output->xdg_output_resources);
G_OBJECT_CLASS (meta_wayland_output_parent_class)->finalize (object); G_OBJECT_CLASS (meta_wayland_output_parent_class)->finalize (object);
} }