Fix FD leaks in VideoViewsTests on CROS

One leak occurs in case of WrapVulkanImage failure. The other one
is RenderNodeFd leak.

Bug: chromium:1258986

Change-Id: I35b90e4349013168f7f04fbe0e279695f021eee8
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/161781
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Austin Eng <enga@chromium.org>
Commit-Queue: Jie A Chen <jie.a.chen@intel.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
diff --git a/src/dawn/tests/end2end/VideoViewsTests_gbm.cpp b/src/dawn/tests/end2end/VideoViewsTests_gbm.cpp
index c0fc649..1bc55db 100644
--- a/src/dawn/tests/end2end/VideoViewsTests_gbm.cpp
+++ b/src/dawn/tests/end2end/VideoViewsTests_gbm.cpp
@@ -84,7 +84,14 @@
         mGbmDevice = CreateGbmDevice();
     }
 
-    void OnTearDown() override { gbm_device_destroy(mGbmDevice); }
+    void OnTearDown() override {
+        if (mGbmDevice != nullptr) {
+            gbm_device_destroy(mGbmDevice);
+        }
+        if (mRenderNodeFd >= 0) {
+            close(mRenderNodeFd);
+        }
+    }
 
   private:
     gbm_device* CreateGbmDevice() {
@@ -100,17 +107,17 @@
         const uint32_t kRenderNodeEnd = kRenderNodeStart + 16;
         const std::string kRenderNodeTemplate = "/dev/dri/renderD";
 
-        int renderNodeFd = -1;
+        mRenderNodeFd = -1;
         for (uint32_t i = kRenderNodeStart; i < kRenderNodeEnd; i++) {
             std::string renderNode = kRenderNodeTemplate + std::to_string(i);
-            renderNodeFd = open(renderNode.c_str(), O_RDWR);
-            if (renderNodeFd >= 0) {
+            mRenderNodeFd = open(renderNode.c_str(), O_RDWR);
+            if (mRenderNodeFd >= 0) {
                 break;
             }
         }
-        DAWN_ASSERT(renderNodeFd > 0);
+        DAWN_ASSERT(mRenderNodeFd > 0);
 
-        gbm_device* gbmDevice = gbm_create_device(renderNodeFd);
+        gbm_device* gbmDevice = gbm_create_device(mRenderNodeFd);
         DAWN_ASSERT(gbmDevice != nullptr);
         return gbmDevice;
     }
@@ -208,8 +215,14 @@
         descriptor.drmModifier = gbm_bo_get_modifier(gbmBo);
         descriptor.waitFDs = {};
 
-        return std::make_unique<PlatformTextureGbm>(
+        auto texture = std::make_unique<PlatformTextureGbm>(
             native::vulkan::WrapVulkanImage(mWGPUDevice, &descriptor), gbmBo);
+        // The ownership of FD is only transferred in case of a success import. Otherwise cleanup
+        // is still needed to avoid FD leak.
+        if (!texture->wgpuTexture && descriptor.memoryFD >= 0) {
+            close(descriptor.memoryFD);
+        }
+        return texture;
     }
 
     void DestroyVideoTextureForTest(
@@ -229,6 +242,7 @@
 
     WGPUDevice mWGPUDevice = nullptr;
     gbm_device* mGbmDevice = nullptr;
+    int mRenderNodeFd = -1;
 };
 
 }  // anonymous namespace