diff mbox series

[FFmpeg-devel,3/5] avutil/hwcontext_vulkan: Fix leaks when semaphore creation fails

Message ID tencent_DE407D9AC29F8EAB344E8E70312D939A7308@qq.com
State New
Headers show
Series [FFmpeg-devel,1/5] avutil/hwcontext: Don't assume device_uninit is reentrant | expand

Checks

Context Check Description
yinshiyou/make_loongarch64 success Make finished
yinshiyou/make_fate_loongarch64 success Make fate finished
andriy/make_x86 success Make finished
andriy/make_fate_x86 success Make fate finished

Commit Message

Zhao Zhili Feb. 20, 2024, 12:08 p.m. UTC
From: Zhao Zhili <zhilizhao@tencent.com>

---
 libavutil/hwcontext_vulkan.c | 30 +++++++++++++++++++-----------
 1 file changed, 19 insertions(+), 11 deletions(-)

Comments

Zhao Zhili Feb. 20, 2024, 12:23 p.m. UTC | #1
I found serious memory leaks (dozens of frames depends on video filter) when test vulkan, which may or may not directly related to vulkan. See trac 10873.

> 在 2024年2月20日,下午8:08,Zhao Zhili <quinkblack@foxmail.com> 写道:
> 
> From: Zhao Zhili <zhilizhao@tencent.com>
> 
> ---
> libavutil/hwcontext_vulkan.c | 30 +++++++++++++++++++-----------
> 1 file changed, 19 insertions(+), 11 deletions(-)
> 
> diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c
> index a84713e621..c64094f31c 100644
> --- a/libavutil/hwcontext_vulkan.c
> +++ b/libavutil/hwcontext_vulkan.c
> @@ -1807,23 +1807,30 @@ static void vulkan_frame_free(AVHWFramesContext *hwfc, AVVkFrame *f)
>     VulkanDevicePriv *p = hwfc->device_ctx->internal->priv;
>     FFVulkanFunctions *vk = &p->vkctx.vkfn;
>     int nb_images = ff_vk_count_images(f);
> +    int nb_sems = 0;
> +
> +    while (nb_sems < FF_ARRAY_ELEMS(f->sem) && f->sem[nb_sems])
> +        nb_sems++;
> +
> +    if (nb_sems) {
> +        VkSemaphoreWaitInfo sem_wait = {
> +            .sType          = VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO,
> +            .flags          = 0x0,
> +            .pSemaphores    = f->sem,
> +            .pValues        = f->sem_value,
> +            .semaphoreCount = nb_sems,
> +        };
> 
> -    VkSemaphoreWaitInfo sem_wait = {
> -        .sType          = VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO,
> -        .flags          = 0x0,
> -        .pSemaphores    = f->sem,
> -        .pValues        = f->sem_value,
> -        .semaphoreCount = nb_images,
> -    };
> -
> -    vk->WaitSemaphores(hwctx->act_dev, &sem_wait, UINT64_MAX);
> +        vk->WaitSemaphores(hwctx->act_dev, &sem_wait, UINT64_MAX);
> +    }
> 
>     vulkan_free_internal(f);
> 
>     for (int i = 0; i < nb_images; i++) {
>         vk->DestroyImage(hwctx->act_dev,     f->img[i], hwctx->alloc);
>         vk->FreeMemory(hwctx->act_dev,       f->mem[i], hwctx->alloc);
> -        vk->DestroySemaphore(hwctx->act_dev, f->sem[i], hwctx->alloc);
> +        if (f->sem[i])
> +            vk->DestroySemaphore(hwctx->act_dev, f->sem[i], hwctx->alloc);
>     }
> 
>     av_free(f);
> @@ -2098,7 +2105,8 @@ static int create_frame(AVHWFramesContext *hwfc, AVVkFrame **frame,
>         if (ret != VK_SUCCESS) {
>             av_log(hwctx, AV_LOG_ERROR, "Failed to create semaphore: %s\n",
>                    ff_vk_ret2str(ret));
> -            return AVERROR_EXTERNAL;
> +            err = AVERROR_EXTERNAL;
> +            goto fail;
>         }
> 
>         f->queue_family[i] = p->nb_img_qfs > 1 ? VK_QUEUE_FAMILY_IGNORED : p->img_qfs[0];
> -- 
> 2.34.1
> 
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
> 
> To unsubscribe, visit link above, or email
Lynne Feb. 20, 2024, 5:10 p.m. UTC | #2
Feb 20, 2024, 13:10 by quinkblack@foxmail.com:

> From: Zhao Zhili <zhilizhao@tencent.com>
>
> ---
>  libavutil/hwcontext_vulkan.c | 30 +++++++++++++++++++-----------
>  1 file changed, 19 insertions(+), 11 deletions(-)
>
> diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c
> index a84713e621..c64094f31c 100644
> --- a/libavutil/hwcontext_vulkan.c
> +++ b/libavutil/hwcontext_vulkan.c
> @@ -1807,23 +1807,30 @@ static void vulkan_frame_free(AVHWFramesContext *hwfc, AVVkFrame *f)
>  VulkanDevicePriv *p = hwfc->device_ctx->internal->priv;
>  FFVulkanFunctions *vk = &p->vkctx.vkfn;
>  int nb_images = ff_vk_count_images(f);
> +    int nb_sems = 0;
> +
> +    while (nb_sems < FF_ARRAY_ELEMS(f->sem) && f->sem[nb_sems])
> +        nb_sems++;
> +
> +    if (nb_sems) {
> +        VkSemaphoreWaitInfo sem_wait = {
> +            .sType          = VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO,
> +            .flags          = 0x0,
> +            .pSemaphores    = f->sem,
> +            .pValues        = f->sem_value,
> +            .semaphoreCount = nb_sems,
> +        };
>  
> -    VkSemaphoreWaitInfo sem_wait = {
> -        .sType          = VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO,
> -        .flags          = 0x0,
> -        .pSemaphores    = f->sem,
> -        .pValues        = f->sem_value,
> -        .semaphoreCount = nb_images,
> -    };
> -
> -    vk->WaitSemaphores(hwctx->act_dev, &sem_wait, UINT64_MAX);
> +        vk->WaitSemaphores(hwctx->act_dev, &sem_wait, UINT64_MAX);
> +    }
>  
>  vulkan_free_internal(f);
>  
>  for (int i = 0; i < nb_images; i++) {
>  vk->DestroyImage(hwctx->act_dev,     f->img[i], hwctx->alloc);
>  vk->FreeMemory(hwctx->act_dev,       f->mem[i], hwctx->alloc);
> -        vk->DestroySemaphore(hwctx->act_dev, f->sem[i], hwctx->alloc);
> +        if (f->sem[i])
> +            vk->DestroySemaphore(hwctx->act_dev, f->sem[i], hwctx->alloc);
>

vkDestroySemaphore should already check for NULL, though?
Zhao Zhili Feb. 20, 2024, 5:58 p.m. UTC | #3
On 2024/2/21 01:10, Lynne wrote:
> Feb 20, 2024, 13:10 by quinkblack@foxmail.com:
>
>> From: Zhao Zhili <zhilizhao@tencent.com>
>>
>> ---
>>   libavutil/hwcontext_vulkan.c | 30 +++++++++++++++++++-----------
>>   1 file changed, 19 insertions(+), 11 deletions(-)
>>
>> diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c
>> index a84713e621..c64094f31c 100644
>> --- a/libavutil/hwcontext_vulkan.c
>> +++ b/libavutil/hwcontext_vulkan.c
>> @@ -1807,23 +1807,30 @@ static void vulkan_frame_free(AVHWFramesContext *hwfc, AVVkFrame *f)
>>   VulkanDevicePriv *p = hwfc->device_ctx->internal->priv;
>>   FFVulkanFunctions *vk = &p->vkctx.vkfn;
>>   int nb_images = ff_vk_count_images(f);
>> +    int nb_sems = 0;
>> +
>> +    while (nb_sems < FF_ARRAY_ELEMS(f->sem) && f->sem[nb_sems])
>> +        nb_sems++;
>> +
>> +    if (nb_sems) {
>> +        VkSemaphoreWaitInfo sem_wait = {
>> +            .sType          = VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO,
>> +            .flags          = 0x0,
>> +            .pSemaphores    = f->sem,
>> +            .pValues        = f->sem_value,
>> +            .semaphoreCount = nb_sems,
>> +        };
>>   
>> -    VkSemaphoreWaitInfo sem_wait = {
>> -        .sType          = VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO,
>> -        .flags          = 0x0,
>> -        .pSemaphores    = f->sem,
>> -        .pValues        = f->sem_value,
>> -        .semaphoreCount = nb_images,
>> -    };
>> -
>> -    vk->WaitSemaphores(hwctx->act_dev, &sem_wait, UINT64_MAX);
>> +        vk->WaitSemaphores(hwctx->act_dev, &sem_wait, UINT64_MAX);
>> +    }
>>   
>>   vulkan_free_internal(f);
>>   
>>   for (int i = 0; i < nb_images; i++) {
>>   vk->DestroyImage(hwctx->act_dev,     f->img[i], hwctx->alloc);
>>   vk->FreeMemory(hwctx->act_dev,       f->mem[i], hwctx->alloc);
>> -        vk->DestroySemaphore(hwctx->act_dev, f->sem[i], hwctx->alloc);
>> +        if (f->sem[i])
>> +            vk->DestroySemaphore(hwctx->act_dev, f->sem[i], hwctx->alloc);
>>
> vkDestroySemaphore should already check for NULL, though?

Yes, the check before vkDestroySemaphore can be removed. Will update the 
patch.

> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
> To unsubscribe, visit link above, or email
> ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
diff mbox series

Patch

diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c
index a84713e621..c64094f31c 100644
--- a/libavutil/hwcontext_vulkan.c
+++ b/libavutil/hwcontext_vulkan.c
@@ -1807,23 +1807,30 @@  static void vulkan_frame_free(AVHWFramesContext *hwfc, AVVkFrame *f)
     VulkanDevicePriv *p = hwfc->device_ctx->internal->priv;
     FFVulkanFunctions *vk = &p->vkctx.vkfn;
     int nb_images = ff_vk_count_images(f);
+    int nb_sems = 0;
+
+    while (nb_sems < FF_ARRAY_ELEMS(f->sem) && f->sem[nb_sems])
+        nb_sems++;
+
+    if (nb_sems) {
+        VkSemaphoreWaitInfo sem_wait = {
+            .sType          = VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO,
+            .flags          = 0x0,
+            .pSemaphores    = f->sem,
+            .pValues        = f->sem_value,
+            .semaphoreCount = nb_sems,
+        };
 
-    VkSemaphoreWaitInfo sem_wait = {
-        .sType          = VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO,
-        .flags          = 0x0,
-        .pSemaphores    = f->sem,
-        .pValues        = f->sem_value,
-        .semaphoreCount = nb_images,
-    };
-
-    vk->WaitSemaphores(hwctx->act_dev, &sem_wait, UINT64_MAX);
+        vk->WaitSemaphores(hwctx->act_dev, &sem_wait, UINT64_MAX);
+    }
 
     vulkan_free_internal(f);
 
     for (int i = 0; i < nb_images; i++) {
         vk->DestroyImage(hwctx->act_dev,     f->img[i], hwctx->alloc);
         vk->FreeMemory(hwctx->act_dev,       f->mem[i], hwctx->alloc);
-        vk->DestroySemaphore(hwctx->act_dev, f->sem[i], hwctx->alloc);
+        if (f->sem[i])
+            vk->DestroySemaphore(hwctx->act_dev, f->sem[i], hwctx->alloc);
     }
 
     av_free(f);
@@ -2098,7 +2105,8 @@  static int create_frame(AVHWFramesContext *hwfc, AVVkFrame **frame,
         if (ret != VK_SUCCESS) {
             av_log(hwctx, AV_LOG_ERROR, "Failed to create semaphore: %s\n",
                    ff_vk_ret2str(ret));
-            return AVERROR_EXTERNAL;
+            err = AVERROR_EXTERNAL;
+            goto fail;
         }
 
         f->queue_family[i] = p->nb_img_qfs > 1 ? VK_QUEUE_FAMILY_IGNORED : p->img_qfs[0];