Fix RenderArea use after free error
When RenderEngine is single threaded, renderScreenImpl immediately calls present instead of moving it into the returned future. This caused the unique_ptr<RenderArea> to be destroyed when renderScreenImpl returned, deleting RenderArea prematurely. We can use a shared_ptr to ensure that RenderArea is only deleted once both captureScreenCommon and present no longer need it.
Bug: 264827546
Test: atest ScreenCaptureTest
Test: go/wm-smoke
Change-Id: I8b591bec7c6ad07df9fa9b7f62495dac10a68a93
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index b930477..2df3c22 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -6509,7 +6509,7 @@
[=, renderAreaFuture = std::move(renderAreaFuture)]() FTL_FAKE_GUARD(
kMainThreadContext) mutable -> ftl::SharedFuture<FenceResult> {
ScreenCaptureResults captureResults;
- std::unique_ptr<RenderArea> renderArea = renderAreaFuture.get();
+ std::shared_ptr<RenderArea> renderArea = renderAreaFuture.get();
if (!renderArea) {
ALOGW("Skipping screen capture because of invalid render area.");
if (captureListener) {
@@ -6521,7 +6521,7 @@
ftl::SharedFuture<FenceResult> renderFuture;
renderArea->render([&]() FTL_FAKE_GUARD(kMainThreadContext) {
- renderFuture = renderScreenImpl(std::move(renderArea), traverseLayers, buffer,
+ renderFuture = renderScreenImpl(renderArea, traverseLayers, buffer,
canCaptureBlackoutContent, regionSampling,
grayscale, captureResults);
});
@@ -6549,7 +6549,7 @@
}
ftl::SharedFuture<FenceResult> SurfaceFlinger::renderScreenImpl(
- std::unique_ptr<RenderArea> renderArea, TraverseLayersFunction traverseLayers,
+ std::shared_ptr<const RenderArea> renderArea, TraverseLayersFunction traverseLayers,
const std::shared_ptr<renderengine::ExternalTexture>& buffer,
bool canCaptureBlackoutContent, bool regionSampling, bool grayscale,
ScreenCaptureResults& captureResults) {