screenshooter: Add SHM buffer destroy listener to avoid invalid memcpy
This adds a destroy listener on the SHM buffer provided by our client. It will unregister the frame notify listener in case our buffer is destroyed before the frame signal is emitted and thus avoid a memcpy to invalid memory. Signed-off-by: Paul Kocialkowski <paul.kocialkowski@bootlin.com> (cherry picked from commit 0afd3428dc899c426d37650192f828541f70e390)
This commit is contained in:
committed by
Marius Vlad
parent
5517953ed0
commit
7678ec9209
@@ -45,7 +45,8 @@
|
||||
#include "wcap/wcap-decode.h"
|
||||
|
||||
struct screenshooter_frame_listener {
|
||||
struct wl_listener listener;
|
||||
struct wl_listener frame_listener;
|
||||
struct wl_listener buffer_destroy_listener;
|
||||
struct weston_buffer *buffer;
|
||||
struct weston_output *output;
|
||||
weston_screenshooter_done_func_t done;
|
||||
@@ -120,7 +121,8 @@ screenshooter_frame_notify(struct wl_listener *listener, void *data)
|
||||
{
|
||||
struct screenshooter_frame_listener *l =
|
||||
container_of(listener,
|
||||
struct screenshooter_frame_listener, listener);
|
||||
struct screenshooter_frame_listener,
|
||||
frame_listener);
|
||||
struct weston_output *output = l->output;
|
||||
struct weston_compositor *compositor = output->compositor;
|
||||
const pixman_format_code_t pixman_format =
|
||||
@@ -130,6 +132,8 @@ screenshooter_frame_notify(struct wl_listener *listener, void *data)
|
||||
|
||||
weston_output_disable_planes_decr(output);
|
||||
wl_list_remove(&listener->link);
|
||||
wl_list_remove(&l->buffer_destroy_listener.link);
|
||||
|
||||
stride = l->buffer->width * (PIXMAN_FORMAT_BPP(pixman_format) / 8);
|
||||
pixels = malloc(stride * l->buffer->height);
|
||||
|
||||
@@ -177,6 +181,22 @@ screenshooter_frame_notify(struct wl_listener *listener, void *data)
|
||||
free(l);
|
||||
}
|
||||
|
||||
static void
|
||||
buffer_destroy_handle(struct wl_listener *listener, void *data)
|
||||
{
|
||||
struct screenshooter_frame_listener *l =
|
||||
container_of(listener,
|
||||
struct screenshooter_frame_listener,
|
||||
buffer_destroy_listener);
|
||||
|
||||
weston_output_disable_planes_decr(l->output);
|
||||
wl_list_remove(&listener->link);
|
||||
wl_list_remove(&l->frame_listener.link);
|
||||
l->done(l->data, WESTON_SCREENSHOOTER_BAD_BUFFER);
|
||||
|
||||
free(l);
|
||||
}
|
||||
|
||||
WL_EXPORT int
|
||||
weston_screenshooter_shoot(struct weston_output *output,
|
||||
struct weston_buffer *buffer,
|
||||
@@ -205,8 +225,13 @@ weston_screenshooter_shoot(struct weston_output *output,
|
||||
l->output = output;
|
||||
l->done = done;
|
||||
l->data = data;
|
||||
l->listener.notify = screenshooter_frame_notify;
|
||||
wl_signal_add(&output->frame_signal, &l->listener);
|
||||
|
||||
l->frame_listener.notify = screenshooter_frame_notify;
|
||||
wl_signal_add(&output->frame_signal, &l->frame_listener);
|
||||
|
||||
l->buffer_destroy_listener.notify = buffer_destroy_handle;
|
||||
wl_signal_add(&buffer->destroy_signal, &l->buffer_destroy_listener);
|
||||
|
||||
weston_output_disable_planes_incr(output);
|
||||
weston_output_schedule_repaint(output);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user