mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2026-08-09 01:21:06 +00:00
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.
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -516,6 +516,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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -123,6 +123,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);
|
||||
|
||||
Reference in New Issue
Block a user