hwcontext_vulkan: do not segfault when failing to init a AVHWFramesContext

frames_uninit is always called on failure, and the free_exec_ctx function
did not zero the pool when freeing it, so it resulted in a double free.
This commit is contained in:
Lynne 2020-11-25 12:06:00 +01:00
parent 18a6535b08
commit 7b274a9b89
No known key found for this signature in database
GPG Key ID: A2FEA5F03F034464

View File

@ -752,14 +752,6 @@ static int create_exec_ctx(AVHWFramesContext *hwfc, VulkanExecCtx *cmd,
cmd->nb_queues = num_queues;
cmd->queues = av_mallocz(num_queues * sizeof(*cmd->queues));
if (!cmd->queues)
return AVERROR(ENOMEM);
cmd->bufs = av_mallocz(num_queues * sizeof(*cmd->bufs));
if (!cmd->bufs)
return AVERROR(ENOMEM);
/* Create command pool */
ret = vkCreateCommandPool(hwctx->act_dev, &cqueue_create,
hwctx->alloc, &cmd->pool);
@ -769,6 +761,10 @@ static int create_exec_ctx(AVHWFramesContext *hwfc, VulkanExecCtx *cmd,
return AVERROR_EXTERNAL;
}
cmd->bufs = av_mallocz(num_queues * sizeof(*cmd->bufs));
if (!cmd->bufs)
return AVERROR(ENOMEM);
cbuf_create.commandPool = cmd->pool;
/* Allocate command buffer */
@ -776,9 +772,14 @@ static int create_exec_ctx(AVHWFramesContext *hwfc, VulkanExecCtx *cmd,
if (ret != VK_SUCCESS) {
av_log(hwfc, AV_LOG_ERROR, "Command buffer alloc failure: %s\n",
vk_ret2str(ret));
av_freep(&cmd->bufs);
return AVERROR_EXTERNAL;
}
cmd->queues = av_mallocz(num_queues * sizeof(*cmd->queues));
if (!cmd->queues)
return AVERROR(ENOMEM);
for (int i = 0; i < num_queues; i++) {
VulkanQueueCtx *q = &cmd->queues[i];
vkGetDeviceQueue(hwctx->act_dev, queue_family_index, i, &q->queue);
@ -792,23 +793,25 @@ static void free_exec_ctx(AVHWFramesContext *hwfc, VulkanExecCtx *cmd)
{
AVVulkanDeviceContext *hwctx = hwfc->device_ctx->hwctx;
/* Make sure all queues have finished executing */
for (int i = 0; i < cmd->nb_queues; i++) {
VulkanQueueCtx *q = &cmd->queues[i];
if (cmd->queues) {
for (int i = 0; i < cmd->nb_queues; i++) {
VulkanQueueCtx *q = &cmd->queues[i];
if (q->fence && !q->was_synchronous) {
vkWaitForFences(hwctx->act_dev, 1, &q->fence, VK_TRUE, UINT64_MAX);
vkResetFences(hwctx->act_dev, 1, &q->fence);
/* Make sure all queues have finished executing */
if (q->fence && !q->was_synchronous) {
vkWaitForFences(hwctx->act_dev, 1, &q->fence, VK_TRUE, UINT64_MAX);
vkResetFences(hwctx->act_dev, 1, &q->fence);
}
/* Free the fence */
if (q->fence)
vkDestroyFence(hwctx->act_dev, q->fence, hwctx->alloc);
/* Free buffer dependencies */
for (int j = 0; j < q->nb_buf_deps; j++)
av_buffer_unref(&q->buf_deps[j]);
av_free(q->buf_deps);
}
/* Free the fence */
if (q->fence)
vkDestroyFence(hwctx->act_dev, q->fence, hwctx->alloc);
/* Free buffer dependencies */
for (int j = 0; j < q->nb_buf_deps; j++)
av_buffer_unref(&q->buf_deps[j]);
av_free(q->buf_deps);
}
if (cmd->bufs)
@ -816,8 +819,9 @@ static void free_exec_ctx(AVHWFramesContext *hwfc, VulkanExecCtx *cmd)
if (cmd->pool)
vkDestroyCommandPool(hwctx->act_dev, cmd->pool, hwctx->alloc);
av_freep(&cmd->bufs);
av_freep(&cmd->queues);
av_freep(&cmd->bufs);
cmd->pool = NULL;
}
static VkCommandBuffer get_buf_exec_ctx(AVHWFramesContext *hwfc, VulkanExecCtx *cmd)
@ -1719,24 +1723,24 @@ static int vulkan_frames_init(AVHWFramesContext *hwfc)
dev_hwctx->queue_family_comp_index,
GET_QUEUE_COUNT(dev_hwctx, 0, 1, 0));
if (err)
goto fail;
return err;
err = create_exec_ctx(hwfc, &fp->upload_ctx,
dev_hwctx->queue_family_tx_index,
GET_QUEUE_COUNT(dev_hwctx, 0, 0, 1));
if (err)
goto fail;
return err;
err = create_exec_ctx(hwfc, &fp->download_ctx,
dev_hwctx->queue_family_tx_index, 1);
if (err)
goto fail;
return err;
/* Test to see if allocation will fail */
err = create_frame(hwfc, &f, hwctx->tiling, hwctx->usage,
hwctx->create_pnext);
if (err)
goto fail;
return err;
vulkan_frame_free(hwfc, (uint8_t *)f);
@ -1746,20 +1750,11 @@ static int vulkan_frames_init(AVHWFramesContext *hwfc)
hwfc->internal->pool_internal = av_buffer_pool_init2(sizeof(AVVkFrame),
hwfc, vulkan_pool_alloc,
NULL);
if (!hwfc->internal->pool_internal) {
err = AVERROR(ENOMEM);
goto fail;
}
if (!hwfc->internal->pool_internal)
return AVERROR(ENOMEM);
}
return 0;
fail:
free_exec_ctx(hwfc, &fp->conv_ctx);
free_exec_ctx(hwfc, &fp->upload_ctx);
free_exec_ctx(hwfc, &fp->download_ctx);
return err;
}
static int vulkan_get_buffer(AVHWFramesContext *hwfc, AVFrame *frame)