[PR] avfilter/dnn: fix nireq deadlock in ONNX backend (PR #24082)

Steven Xiao via ffmpeg-devel <[email protected]>
Newsgroups gmane.comp.video.ffmpeg.devel
Message-ID <178646696091.59.17755215890683435850@29965ddac10e>
PR #24082 opened by Steven Xiao (younengxiao)
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24082
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24082.patch

dnn_load_model_onnx() always allocated exactly one ONNXRequestItem,
but dnn_free_model_onnx() waits via ff_dnn_wait_requests() for the
queue to reach ctx->nireq items. Since a7e72069f1 made that wait
block on a condition variable instead of polling, nireq >= 2 now
hangs forever on teardown instead of exiting.

Fix by allocating ctx->nireq items in a loop, matching the
TensorFlow/OpenVINO backends, and normalizing nireq (default 0) to
av_cpu_count() / 2 + 1 beforehand so the loop isn't skipped.

Signed-off-by: younengxiao <[email protected]>



>From e9976eb5d63476d05321f6f79104d157f9ba317b Mon Sep 17 00:00:00 2001
From: younengxiao <[email protected]>
Date: Tue, 11 Aug 2026 12:45:11 -0400
Subject: [PATCH] avfilter/dnn: fix nireq deadlock in ONNX backend

dnn_load_model_onnx() always allocated exactly one ONNXRequestItem,
but dnn_free_model_onnx() waits via ff_dnn_wait_requests() for the
queue to reach ctx->nireq items. Since a7e72069f1 made that wait
block on a condition variable instead of polling, nireq >= 2 now
hangs forever on teardown instead of exiting.

Fix by allocating ctx->nireq items in a loop, matching the
TensorFlow/OpenVINO backends, and normalizing nireq (default 0) to
av_cpu_count() / 2 + 1 beforehand so the loop isn't skipped.

Signed-off-by: younengxiao <[email protected]>
---
 libavfilter/dnn/dnn_backend_onnx.c | 45 +++++++++++++++++-------------
 1 file changed, 25 insertions(+), 20 deletions(-)

diff --git a/libavfilter/dnn/dnn_backend_onnx.c b/libavfilter/dnn/dnn_backend_onnx.c
index 6c75d6eb24..d264a53736 100644
--- a/libavfilter/dnn/dnn_backend_onnx.c
+++ b/libavfilter/dnn/dnn_backend_onnx.c
@@ -25,6 +25,7 @@
 
 #include "libavutil/opt.h"
 #include "libavutil/avassert.h"
+#include "libavutil/cpu.h"
 #include "libavutil/mem.h"
 #include "libavutil/avstring.h"
 #include "libavutil/thread.h"
@@ -726,7 +727,6 @@ static DNNModel *dnn_load_model_onnx(DnnContext *ctx, DNNFunctionType func_type,
 {
     DNNModel       *model = NULL;
     ONNXModel *onnx_model = NULL;
-    ONNXRequestItem *item = NULL;
     ONNXOptions  *options = &ctx->onnx_option;
     OrtStatus *status;
 
@@ -973,29 +973,37 @@ static DNNModel *dnn_load_model_onnx(DnnContext *ctx, DNNFunctionType func_type,
         }
     }
 
+    if (ctx->nireq <= 0) {
+        // the default value is a rough estimation
+        ctx->nireq = av_cpu_count() / 2 + 1;
+    }
+
     onnx_model->request_queue = ff_safe_queue_create();
     if (!onnx_model->request_queue) {
         goto fail;
     }
 
-    item = av_mallocz(sizeof(ONNXRequestItem));
-    if (!item) {
-        goto fail;
-    }
-    item->lltask = NULL;
-    item->infer_request = onnx_create_inference_request();
-    if (!item->infer_request) {
-        av_log(ctx, AV_LOG_ERROR, "Failed to allocate memory for ONNX inference request\n");
-        goto fail;
-    }
-    item->exec_module.start_inference = &onnx_start_inference;
-    item->exec_module.callback = &infer_completion_callback;
-    item->exec_module.args = item;
+    for (int i = 0; i < ctx->nireq; i++) {
+        ONNXRequestItem *item = av_mallocz(sizeof(*item));
+        if (!item) {
+            goto fail;
+        }
+        item->lltask = NULL;
+        item->infer_request = onnx_create_inference_request();
+        if (!item->infer_request) {
+            av_log(ctx, AV_LOG_ERROR, "Failed to allocate memory for ONNX inference request\n");
+            av_freep(&item);
+            goto fail;
+        }
+        item->exec_module.start_inference = &onnx_start_inference;
+        item->exec_module.callback = &infer_completion_callback;
+        item->exec_module.args = item;
 
-    if (ff_safe_queue_push_back(onnx_model->request_queue, item) < 0) {
-        goto fail;
+        if (ff_safe_queue_push_back(onnx_model->request_queue, item) < 0) {
+            destroy_request_item(&item);
+            goto fail;
+        }
     }
-    item = NULL;
 
     onnx_model->task_queue = ff_queue_create();
     if (!onnx_model->task_queue) {
@@ -1015,9 +1023,6 @@ static DNNModel *dnn_load_model_onnx(DnnContext *ctx, DNNFunctionType func_type,
     return model;
 
 fail:
-    if (item) {
-        destroy_request_item(&item);
-    }
     dnn_free_model_onnx(&model);
     return NULL;
 }
-- 
2.52.0

_______________________________________________
ffmpeg-devel mailing list -- [email protected]
To unsubscribe send an email to [email protected]
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.