mirror of
https://gitlab.freedesktop.org/wayland/weston.git
synced 2026-05-07 06:08:05 +02:00
compositor-wayland: Fix a use after free
When a window is being closed, the frame_done callback often runs after
the output is already destroyed, i.e:
wayland_output_start_repaint_loop
input_handle_button
wayland_output_destroy
frame_done
To fix this, destroy the callback before destroying the output.
(Also, fix the type of output in frame_done: it's passed in
a wayland_output, not a weston_output.)
Signed-off-by: Dima Ryazanov <dima@gmail.com>
Reviewed-by: Daniel Stone <daniels@collabora.com>
This commit is contained in:
parent
e3a582f9ff
commit
89c2f637b9
1 changed files with 14 additions and 9 deletions
|
|
@ -128,6 +128,8 @@ struct wayland_output {
|
||||||
|
|
||||||
struct weston_mode mode;
|
struct weston_mode mode;
|
||||||
uint32_t scale;
|
uint32_t scale;
|
||||||
|
|
||||||
|
struct wl_callback *frame_cb;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct wayland_parent_output {
|
struct wayland_parent_output {
|
||||||
|
|
@ -342,10 +344,12 @@ wayland_output_get_shm_buffer(struct wayland_output *output)
|
||||||
static void
|
static void
|
||||||
frame_done(void *data, struct wl_callback *callback, uint32_t time)
|
frame_done(void *data, struct wl_callback *callback, uint32_t time)
|
||||||
{
|
{
|
||||||
struct weston_output *output = data;
|
struct wayland_output *output = data;
|
||||||
struct timespec ts;
|
struct timespec ts;
|
||||||
|
|
||||||
|
assert(callback == output->frame_cb);
|
||||||
wl_callback_destroy(callback);
|
wl_callback_destroy(callback);
|
||||||
|
output->frame_cb = NULL;
|
||||||
|
|
||||||
/* XXX: use the presentation extension for proper timings */
|
/* XXX: use the presentation extension for proper timings */
|
||||||
|
|
||||||
|
|
@ -356,8 +360,8 @@ frame_done(void *data, struct wl_callback *callback, uint32_t time)
|
||||||
* we can, and pretend finish_frame time is when we process this
|
* we can, and pretend finish_frame time is when we process this
|
||||||
* event.
|
* event.
|
||||||
*/
|
*/
|
||||||
weston_compositor_read_presentation_clock(output->compositor, &ts);
|
weston_compositor_read_presentation_clock(output->base.compositor, &ts);
|
||||||
weston_output_finish_frame(output, &ts, 0);
|
weston_output_finish_frame(&output->base, &ts, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct wl_callback_listener frame_listener = {
|
static const struct wl_callback_listener frame_listener = {
|
||||||
|
|
@ -458,7 +462,6 @@ wayland_output_start_repaint_loop(struct weston_output *output_base)
|
||||||
struct wayland_output *output = to_wayland_output(output_base);
|
struct wayland_output *output = to_wayland_output(output_base);
|
||||||
struct wayland_backend *wb =
|
struct wayland_backend *wb =
|
||||||
to_wayland_backend(output->base.compositor);
|
to_wayland_backend(output->base.compositor);
|
||||||
struct wl_callback *callback;
|
|
||||||
|
|
||||||
/* If this is the initial frame, we need to attach a buffer so that
|
/* If this is the initial frame, we need to attach a buffer so that
|
||||||
* the compositor can map the surface and include it in its render
|
* the compositor can map the surface and include it in its render
|
||||||
|
|
@ -471,8 +474,8 @@ wayland_output_start_repaint_loop(struct weston_output *output_base)
|
||||||
draw_initial_frame(output);
|
draw_initial_frame(output);
|
||||||
}
|
}
|
||||||
|
|
||||||
callback = wl_surface_frame(output->parent.surface);
|
output->frame_cb = wl_surface_frame(output->parent.surface);
|
||||||
wl_callback_add_listener(callback, &frame_listener, output);
|
wl_callback_add_listener(output->frame_cb, &frame_listener, output);
|
||||||
wl_surface_commit(output->parent.surface);
|
wl_surface_commit(output->parent.surface);
|
||||||
wl_display_flush(wb->parent.wl_display);
|
wl_display_flush(wb->parent.wl_display);
|
||||||
}
|
}
|
||||||
|
|
@ -483,10 +486,9 @@ wayland_output_repaint_gl(struct weston_output *output_base,
|
||||||
{
|
{
|
||||||
struct wayland_output *output = to_wayland_output(output_base);
|
struct wayland_output *output = to_wayland_output(output_base);
|
||||||
struct weston_compositor *ec = output->base.compositor;
|
struct weston_compositor *ec = output->base.compositor;
|
||||||
struct wl_callback *callback;
|
|
||||||
|
|
||||||
callback = wl_surface_frame(output->parent.surface);
|
output->frame_cb = wl_surface_frame(output->parent.surface);
|
||||||
wl_callback_add_listener(callback, &frame_listener, output);
|
wl_callback_add_listener(output->frame_cb, &frame_listener, output);
|
||||||
|
|
||||||
wayland_output_update_gl_border(output);
|
wayland_output_update_gl_border(output);
|
||||||
|
|
||||||
|
|
@ -693,6 +695,9 @@ wayland_output_destroy(struct weston_output *base)
|
||||||
|
|
||||||
weston_output_destroy(&output->base);
|
weston_output_destroy(&output->base);
|
||||||
|
|
||||||
|
if (output->frame_cb)
|
||||||
|
wl_callback_destroy(output->frame_cb);
|
||||||
|
|
||||||
free(output);
|
free(output);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue