libweston: add weston_view_set_output()

Instead of desktop shell assigning view outputs directly,
use a new method, weston_view_set_output(). The method can
set up an output destroy listener to make sure that views
do not have stale output pointers.

Without this patch it is possible to end up in a scenario
where, e.g. configure_static_view() accesses memory that
has already been freed. The scenario can be provoked by
repeatedly plugging and unplugging a display. The faulty
memory accesses are reported by valgrind.

Signed-off-by: Semi Malinen <semi.malinen@ge.com>
Signed-off-by: Fabien Lahoudere <fabien.lahoudere@collabora.com>
Reviewed-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>
This commit is contained in:
Semi Malinen
2018-04-26 11:08:10 +02:00
committed by Pekka Paalanen
parent 03dc95a131
commit e7a52fbb7d
3 changed files with 52 additions and 6 deletions
+41 -2
View File
@@ -1022,6 +1022,45 @@ weston_surface_update_output_mask(struct weston_surface *es, uint32_t mask)
}
}
static void
notify_view_output_destroy(struct wl_listener *listener, void *data)
{
struct weston_view *view =
container_of(listener,
struct weston_view, output_destroy_listener);
view->output = NULL;
view->output_destroy_listener.notify = NULL;
}
/** Set the primary output of the view
*
* \param view The view whose primary output to set
* \param output The new primary output for the view
*
* Set \a output to be the primary output of the \a view.
*
* Notice that the assignment may be temporary; the primary output could be
* automatically changed. Hence, one cannot rely on the value persisting.
*
* Passing NULL as /a output will set the primary output to NULL.
*/
WL_EXPORT void
weston_view_set_output(struct weston_view *view, struct weston_output *output)
{
if (view->output_destroy_listener.notify) {
wl_list_remove(&view->output_destroy_listener.link);
view->output_destroy_listener.notify = NULL;
}
view->output = output;
if (output) {
view->output_destroy_listener.notify =
notify_view_output_destroy;
wl_signal_add(&output->destroy_signal,
&view->output_destroy_listener);
}
}
/** Recalculate which output(s) the surface has views displayed on
*
* \param es The surface to remap to outputs
@@ -1113,7 +1152,7 @@ weston_view_assign_output(struct weston_view *ev)
}
pixman_region32_fini(&region);
ev->output = new_output;
weston_view_set_output(ev, new_output);
ev->output_mask = mask;
weston_surface_assign_output(ev->surface);
@@ -1823,7 +1862,7 @@ weston_view_unmap(struct weston_view *view)
return;
weston_view_damage_below(view);
view->output = NULL;
weston_view_set_output(view, NULL);
view->plane = NULL;
view->is_mapped = false;
weston_layer_entry_remove(&view->layer_link);
+4
View File
@@ -1183,6 +1183,7 @@ struct weston_view {
* view, inheriting the primary output for related views in shells, etc.
*/
struct weston_output *output;
struct wl_listener output_destroy_listener;
/*
* A more complete representation of all outputs this surface is
@@ -1397,6 +1398,9 @@ enum weston_activate_flag {
void
weston_version(int *major, int *minor, int *micro);
void
weston_view_set_output(struct weston_view *view, struct weston_output *output);
void
weston_view_update_transform(struct weston_view *view);