[PATCH] egl: refcount wl_egl_window objects. fix memory corruption
Kristian Høgsberg
hoegsberg at gmail.com
Wed Oct 23 00:24:17 CEST 2013
On Mon, Oct 07, 2013 at 10:09:17PM +0200, Giulio Camuffo wrote:
> Suppose we create a wl_egl_window and an EGLSurface. Then we call
> eglMakeCurrent(dpy,surf,surf,ctx) with that surface, render and swap.
> Later we destroy the surface and the window, and we make current
> another surface. That resulted in two invalid writes because
> the surface, which is refcounted, gets actually deleted at the
> eglMakeCurrent() call, and in dri2_destroy_surface() its window
> was used, window which was deleted earlier.
> So make also wl_egl_window refcounted, so that it isn't destroyed
> while its surface is still alive.
Just for reference, we discussed this in IRC and it came down to a
misunderstanding of how EGL works. An EGLSurface is current for a
context from eglMakeCurrent up until eglMakeCurrent is called for the
conetxte with another surface or the context is destroyed. The
wl_egl_surface (the native window object) has to be available (can not
be destroyed) for the entire time the EGLSurface exists.
Kristian
> Cc: mesa-stable at lists.freedesktop.org
> ---
> src/egl/drivers/dri2/platform_wayland.c | 3 +++
> src/egl/wayland/wayland-egl/wayland-egl-priv.h | 2 ++
> src/egl/wayland/wayland-egl/wayland-egl.c | 5 ++++-
> 3 files changed, 9 insertions(+), 1 deletion(-)
>
> diff --git a/src/egl/drivers/dri2/platform_wayland.c b/src/egl/drivers/dri2/platform_wayland.c
> index 1d417bb..831cd23 100644
> --- a/src/egl/drivers/dri2/platform_wayland.c
> +++ b/src/egl/drivers/dri2/platform_wayland.c
> @@ -143,6 +143,7 @@ dri2_create_surface(_EGLDriver *drv, _EGLDisplay *disp, EGLint type,
>
> dri2_surf->wl_win->private = dri2_surf;
> dri2_surf->wl_win->resize_callback = resize_callback;
> + ++dri2_surf->wl_win->ref_count;
>
> dri2_surf->base.Width = -1;
> dri2_surf->base.Height = -1;
> @@ -222,6 +223,8 @@ dri2_destroy_surface(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf)
> dri2_surf->wl_win->resize_callback = NULL;
> }
>
> + (dri2_surf->wl_win->destroy)(dri2_surf->wl_win);
> +
> free(surf);
>
> return EGL_TRUE;
> diff --git a/src/egl/wayland/wayland-egl/wayland-egl-priv.h b/src/egl/wayland/wayland-egl/wayland-egl-priv.h
> index da25be9..302e2cf 100644
> --- a/src/egl/wayland/wayland-egl/wayland-egl-priv.h
> +++ b/src/egl/wayland/wayland-egl/wayland-egl-priv.h
> @@ -25,8 +25,10 @@ struct wl_egl_window {
> int attached_width;
> int attached_height;
>
> + int ref_count;
> void *private;
> void (*resize_callback)(struct wl_egl_window *, void *);
> + void (*destroy)(struct wl_egl_window *);
> };
>
> #ifdef __cplusplus
> diff --git a/src/egl/wayland/wayland-egl/wayland-egl.c b/src/egl/wayland/wayland-egl/wayland-egl.c
> index 8bd49cf..7a93987 100644
> --- a/src/egl/wayland/wayland-egl/wayland-egl.c
> +++ b/src/egl/wayland/wayland-egl/wayland-egl.c
> @@ -34,6 +34,8 @@ wl_egl_window_create(struct wl_surface *surface,
> wl_egl_window_resize(egl_window, width, height, 0, 0);
> egl_window->attached_width = 0;
> egl_window->attached_height = 0;
> + egl_window->ref_count = 1;
> + egl_window->destroy = wl_egl_window_destroy;
>
> return egl_window;
> }
> @@ -41,7 +43,8 @@ wl_egl_window_create(struct wl_surface *surface,
> WL_EGL_EXPORT void
> wl_egl_window_destroy(struct wl_egl_window *egl_window)
> {
> - free(egl_window);
> + if (--egl_window->ref_count < 1)
> + free(egl_window);
> }
>
> WL_EGL_EXPORT void
> --
> 1.8.4
>
> _______________________________________________
> wayland-devel mailing list
> wayland-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/wayland-devel
More information about the wayland-devel
mailing list