This is an automated email from the git hooks/post-receive script.

Git pushed a commit to branch release/9.0
in repository ffmpeg.

commit eebd95977f3c78b01dfaf0d863e2bdaa72f84e88
Author:     Raja-89 <[email protected]>
AuthorDate: Thu Jul 23 23:22:32 2026 +0530
Commit:     Michael Niedermayer <[email protected]>
CommitDate: Sun Aug 2 06:24:00 2026 +0200

    avfilter/dnn: fix async teardown race condition in all backends
    
    When the filter graph is torn down early (e.g. at EOF with -frames:v),
    the main thread calls dnn_free_model and destroys the request queue
    while async inference threads may still be running. When a detached
    thread finishes and tries to push its result back to the destroyed
    queue, it triggers a segmentation fault.
    
    Add ff_dnn_wait_requests() to dnn_backend_common which blocks
    until all allocated request items (ctx->nireq) have been safely
    returned to the request_queue. Call it from dnn_free_model in the
    torch, tensorflow, openvino, and onnx backends before destroying the queue.
    
    (cherry picked from commit b52c71e43813952650a74c57b2f31bd0166600ba)
    Co-Authored-by: Fable 5
---
 libavfilter/dnn/dnn_backend_common.c   |  9 +++++++++
 libavfilter/dnn/dnn_backend_common.h   | 11 +++++++++++
 libavfilter/dnn/dnn_backend_onnx.c     |  1 +
 libavfilter/dnn/dnn_backend_openvino.c |  1 +
 libavfilter/dnn/dnn_backend_tf.c       |  1 +
 libavfilter/dnn/dnn_backend_torch.cpp  |  1 +
 6 files changed, 24 insertions(+)

diff --git a/libavfilter/dnn/dnn_backend_common.c 
b/libavfilter/dnn/dnn_backend_common.c
index e45eefd14d..4d6752ae33 100644
--- a/libavfilter/dnn/dnn_backend_common.c
+++ b/libavfilter/dnn/dnn_backend_common.c
@@ -22,6 +22,7 @@
  */
 
 #include "libavutil/mem.h"
+#include "libavutil/time.h"
 #include "dnn_backend_common.h"
 
 #define DNN_ASYNC_SUCCESS (void *)0
@@ -102,6 +103,14 @@ int ff_dnn_async_module_cleanup(DNNAsyncExecModule 
*async_module)
     return 0;
 }
 
+void ff_dnn_wait_requests(SafeQueue *request_queue, int nireq)
+{
+    if (!request_queue)
+        return;
+    while (ff_safe_queue_size(request_queue) < nireq)
+        av_usleep(10000);
+}
+
 int ff_dnn_start_inference_async(void *ctx, DNNAsyncExecModule *async_module)
 {
     int ret;
diff --git a/libavfilter/dnn/dnn_backend_common.h 
b/libavfilter/dnn/dnn_backend_common.h
index 9f5d37b3e0..f0b8b47397 100644
--- a/libavfilter/dnn/dnn_backend_common.h
+++ b/libavfilter/dnn/dnn_backend_common.h
@@ -25,6 +25,7 @@
 #define AVFILTER_DNN_DNN_BACKEND_COMMON_H
 
 #include "queue.h"
+#include "safe_queue.h"
 #include "../dnn_interface.h"
 #include "libavutil/thread.h"
 
@@ -112,6 +113,16 @@ int ff_dnn_fill_task(TaskItem *task, DNNExecBaseParams 
*exec_params, void *backe
  */
 int ff_dnn_async_module_cleanup(DNNAsyncExecModule *async_module);
 
+/**
+ * Wait for all inference requests to complete before teardown.
+ * This blocks the calling thread until all request items have been
+ * returned to the request_queue by the async inference threads.
+ *
+ * @param request_queue pointer to the SafeQueue holding request items
+ * @param nireq total number of allocated request items
+ */
+void ff_dnn_wait_requests(SafeQueue *request_queue, int nireq);
+
 /**
  * Start asynchronous inference routine for the TensorFlow
  * model on a detached thread. It calls the completion callback
diff --git a/libavfilter/dnn/dnn_backend_onnx.c 
b/libavfilter/dnn/dnn_backend_onnx.c
index 0ff0ffb285..6c75d6eb24 100644
--- a/libavfilter/dnn/dnn_backend_onnx.c
+++ b/libavfilter/dnn/dnn_backend_onnx.c
@@ -152,6 +152,7 @@ static void dnn_free_model_onnx(DNNModel **model)
 
     onnx_model = (ONNXModel *)(*model);
 
+    ff_dnn_wait_requests(onnx_model->request_queue, onnx_model->ctx->nireq);
     while (ff_safe_queue_size(onnx_model->request_queue) != 0) {
         ONNXRequestItem *item = (ONNXRequestItem 
*)ff_safe_queue_pop_front(onnx_model->request_queue);
         destroy_request_item(&item);
diff --git a/libavfilter/dnn/dnn_backend_openvino.c 
b/libavfilter/dnn/dnn_backend_openvino.c
index ec46e29b8a..764e8dabb5 100644
--- a/libavfilter/dnn/dnn_backend_openvino.c
+++ b/libavfilter/dnn/dnn_backend_openvino.c
@@ -517,6 +517,7 @@ static void dnn_free_model_ov(DNNModel **model)
         return;
 
     ov_model = (OVModel *)(*model);
+    ff_dnn_wait_requests(ov_model->request_queue, ov_model->ctx->nireq);
     while (ff_safe_queue_size(ov_model->request_queue) != 0) {
         OVRequestItem *item = ff_safe_queue_pop_front(ov_model->request_queue);
         if (item && item->infer_request) {
diff --git a/libavfilter/dnn/dnn_backend_tf.c b/libavfilter/dnn/dnn_backend_tf.c
index 48372bea38..07129bcdb6 100644
--- a/libavfilter/dnn/dnn_backend_tf.c
+++ b/libavfilter/dnn/dnn_backend_tf.c
@@ -486,6 +486,7 @@ static void dnn_free_model_tf(DNNModel **model)
         return;
 
     tf_model = (TFModel *)(*model);
+    ff_dnn_wait_requests(tf_model->request_queue, tf_model->ctx->nireq);
     while (ff_safe_queue_size(tf_model->request_queue) != 0) {
         TFRequestItem *item = ff_safe_queue_pop_front(tf_model->request_queue);
         destroy_request_item(&item);
diff --git a/libavfilter/dnn/dnn_backend_torch.cpp 
b/libavfilter/dnn/dnn_backend_torch.cpp
index 24a202f493..5f16234b8e 100644
--- a/libavfilter/dnn/dnn_backend_torch.cpp
+++ b/libavfilter/dnn/dnn_backend_torch.cpp
@@ -121,6 +121,7 @@ static void dnn_free_model_th(DNNModel **model)
     th_model = (THModel *)(*model);
 
     if (th_model->request_queue) {
+        ff_dnn_wait_requests(th_model->request_queue, th_model->ctx->nireq);
         while (ff_safe_queue_size(th_model->request_queue) != 0) {
             THRequestItem *item = (THRequestItem 
*)ff_safe_queue_pop_front(th_model->request_queue);
             destroy_request_item(&item);

_______________________________________________
ffmpeg-cvslog mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to