From af922a8af92a05cbb93d8f64f48798281f81ea9b Mon Sep 17 00:00:00 2001 From: Carlos Alberto Lopez Perez Date: Tue, 25 Jun 2024 23:08:51 +0100 Subject: [PATCH] REGRESSION(b51f539): Fix memory leak when the buffer is destroyed at view-backend-exportable-fdo-egl Since commit b51f539 there is a memory leak each time the wl_resource is destroyed. This can be easily reproduced by repeteadly switching full-screen on/off (pressing F11 key) with Cog on Weston. The memory leak is caused because since b51f539 the wpe_fdo_egl_exported_image object is not cleaned anymore on the bufferDestroyListenerCallback callback. Commit cb6b86a fixed the leak but introduced crashes on some cases, so it was reverted. This is a new attempt at fixing this leak, this adds safeguards to ensure that the image object is not cleaned twice or with the wrong exported status. Related-to: #73 #175 #176 #178 Related-to: https://github.com/Igalia/cog/issues/538 (cherry picked from commit 5b1c5e459868f03f656a70cc15e83b93b90424d6) --- src/view-backend-exportable-fdo-egl.cpp | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/src/view-backend-exportable-fdo-egl.cpp b/src/view-backend-exportable-fdo-egl.cpp index 0031222..abb2859 100644 --- a/src/view-backend-exportable-fdo-egl.cpp +++ b/src/view-backend-exportable-fdo-egl.cpp @@ -247,9 +247,13 @@ class ClientBundleEGL final : public ClientBundle { void releaseImage(struct wpe_fdo_egl_exported_image* image) { - if (image->bufferResource) - viewBackend->releaseBuffer(image->bufferResource); - else + if (!image) + return; + if (image->exported) { + image->exported = false; + if (image->bufferResource) + viewBackend->releaseBuffer(image->bufferResource); + } else deleteImage(image); } @@ -285,7 +289,6 @@ class ClientBundleEGL final : public ClientBundle { { assert(image->eglImage); WS::instanceImpl().destroyImage(image->eglImage); - delete image; } @@ -293,8 +296,13 @@ class ClientBundleEGL final : public ClientBundle { { struct wpe_fdo_egl_exported_image* image; image = wl_container_of(listener, image, bufferDestroyListener); - - image->bufferResource = nullptr; + // The image object is inmediately destroyed here only if it's not currently + // exported, otherwise it's destroyed when the client releases/returns it. + if (image->exported) { + image->exported = false; + image->bufferResource = nullptr; + } else + deleteImage(image); } };