This commit adds the case handling if the asynchronous execution of a request fails by checking the exit status of the thread when joining before starting another execution. On failure, it does the cleanup as well.
Showing the changes to libavfilter (2 of 2 files). Show all
Unified · Split
| @@ -23,6 +23,9 @@ · 22 unmodified lines | |||
| 23 | 23 | ||
| 24 | #include "dnn_backend_common.h" | 24 | #include "dnn_backend_common.h" |
| 25 | 25 | ||
| 26 | #define DNN_ASYNC_SUCCESS (void *)0 | ||
| 27 | #define DNN_ASYNC_FAIL (void *)-1 | ||
| 28 | |||
| 26 | int ff_check_exec_params(void *ctx, DNNBackendType backend, DNNFunctionType func_type, DNNExecBaseParams *exec_params) | 29 | int ff_check_exec_params(void *ctx, DNNBackendType backend, DNNFunctionType func_type, DNNExecBaseParams *exec_params) |
| 27 | { | 30 | { |
| 28 | if (!exec_params) { | 31 | if (!exec_params) { |
| @@ -79,18 +82,25 @@ static void *async_thread_routine(void *args) · 50 unmodified lines | |||
| 79 | DNNAsyncExecModule *async_module = args; | 82 | DNNAsyncExecModule *async_module = args; |
| 80 | void *request = async_module->args; | 83 | void *request = async_module->args; |
| 81 | 84 | ||
| 82 | async_module->start_inference(request); | 85 | if (async_module->start_inference(request) != DNN_SUCCESS) { |
| 86 | return DNN_ASYNC_FAIL; | ||
| 87 | } | ||
| 83 | async_module->callback(request); | 88 | async_module->callback(request); |
| 84 | return NULL; | 89 | return DNN_ASYNC_SUCCESS; |
| 85 | } | 90 | } |
| 86 | 91 | ||
| 87 | DNNReturnType ff_dnn_async_module_cleanup(DNNAsyncExecModule *async_module) | 92 | DNNReturnType ff_dnn_async_module_cleanup(DNNAsyncExecModule *async_module) |
| 88 | { | 93 | { |
| 94 | void *status = 0; | ||
| 89 | if (!async_module) { | 95 | if (!async_module) { |
| 90 | return DNN_ERROR; | 96 | return DNN_ERROR; |
| 91 | } | 97 | } |
| 92 | #if HAVE_PTHREAD_CANCEL | 98 | #if HAVE_PTHREAD_CANCEL |
| 93 | pthread_join(async_module->thread_id, NULL); | 99 | pthread_join(async_module->thread_id, &status); |
| 100 | if (status == DNN_ASYNC_FAIL) { | ||
| 101 | av_log(NULL, AV_LOG_ERROR, "Last Inference Failed.\n"); | ||
| 102 | return DNN_ERROR; | ||
| 103 | } | ||
| 94 | #endif | 104 | #endif |
| 95 | async_module->start_inference = NULL; | 105 | async_module->start_inference = NULL; |
| 96 | async_module->callback = NULL; | 106 | async_module->callback = NULL; |
| @@ -101,6 +111,7 @@ DNNReturnType ff_dnn_async_module_cleanup(DNNAsyncExecModule *async_module) · 4 unmodified lines | |||
| 101 | DNNReturnType ff_dnn_start_inference_async(void *ctx, DNNAsyncExecModule *async_module) | 111 | DNNReturnType ff_dnn_start_inference_async(void *ctx, DNNAsyncExecModule *async_module) |
| 102 | { | 112 | { |
| 103 | int ret; | 113 | int ret; |
| 114 | void *status = 0; | ||
| 104 | 115 | ||
| 105 | if (!async_module) { | 116 | if (!async_module) { |
| 106 | av_log(ctx, AV_LOG_ERROR, "async_module is null when starting async inference.\n"); | 117 | av_log(ctx, AV_LOG_ERROR, "async_module is null when starting async inference.\n"); |
| @@ -108,7 +119,11 @@ DNNReturnType ff_dnn_start_inference_async(void *ctx, DNNAsyncExecModule *async_ · 1 unmodified line | |||
| 108 | } | 119 | } |
| 109 | 120 | ||
| 110 | #if HAVE_PTHREAD_CANCEL | 121 | #if HAVE_PTHREAD_CANCEL |
| 111 | pthread_join(async_module->thread_id, NULL); | 122 | pthread_join(async_module->thread_id, &status); |
| 123 | if (status == DNN_ASYNC_FAIL) { | ||
| 124 | av_log(ctx, AV_LOG_ERROR, "Unable to start inference as previous inference failed.\n"); | ||
| 125 | return DNN_ERROR; | ||
| 126 | } | ||
| 112 | ret = pthread_create(&async_module->thread_id, NULL, async_thread_routine, async_module); | 127 | ret = pthread_create(&async_module->thread_id, NULL, async_thread_routine, async_module); |
| 113 | if (ret != 0) { | 128 | if (ret != 0) { |
| 114 | av_log(ctx, AV_LOG_ERROR, "Unable to start async inference.\n"); | 129 | av_log(ctx, AV_LOG_ERROR, "Unable to start async inference.\n"); |
| @@ -91,6 +91,7 @@ AVFILTER_DEFINE_CLASS(dnn_tensorflow); · 90 unmodified lines | |||
| 91 | 91 | ||
| 92 | static DNNReturnType execute_model_tf(TFRequestItem *request, Queue *inference_queue); | 92 | static DNNReturnType execute_model_tf(TFRequestItem *request, Queue *inference_queue); |
| 93 | static void infer_completion_callback(void *args); | 93 | static void infer_completion_callback(void *args); |
| 94 | static inline void destroy_request_item(TFRequestItem **arg); | ||
| 94 | 95 | ||
| 95 | static void free_buffer(void *data, size_t length) | 96 | static void free_buffer(void *data, size_t length) |
| 96 | { | 97 | { |
| @@ -172,6 +173,10 @@ static DNNReturnType tf_start_inference(void *args) · 75 unmodified lines | |||
| 172 | request->status); | 173 | request->status); |
| 173 | if (TF_GetCode(request->status) != TF_OK) { | 174 | if (TF_GetCode(request->status) != TF_OK) { |
| 174 | av_log(&tf_model->ctx, AV_LOG_ERROR, "%s", TF_Message(request->status)); | 175 | av_log(&tf_model->ctx, AV_LOG_ERROR, "%s", TF_Message(request->status)); |
| 176 | tf_free_request(infer_request); | ||
| 177 | if (ff_safe_queue_push_back(tf_model->request_queue, request) < 0) { | ||
| 178 | destroy_request_item(&request); | ||
| 179 | } | ||
| 175 | return DNN_ERROR; | 180 | return DNN_ERROR; |
| 176 | } | 181 | } |
| 177 | return DNN_SUCCESS; | 182 | return DNN_SUCCESS; |
| @@ -1095,7 +1100,10 @@ static DNNReturnType execute_model_tf(TFRequestItem *request, Queue *inference_q · 917 unmodified lines | |||
| 1095 | } | 1100 | } |
| 1096 | 1101 | ||
| 1097 | if (task->async) { | 1102 | if (task->async) { |
| 1098 | return ff_dnn_start_inference_async(ctx, &request->exec_module); | 1103 | if (ff_dnn_start_inference_async(ctx, &request->exec_module) != DNN_SUCCESS) { |
| 1104 | goto err; | ||
| 1105 | } | ||
| 1106 | return DNN_SUCCESS; | ||
| 1099 | } else { | 1107 | } else { |
| 1100 | if (tf_start_inference(request) != DNN_SUCCESS) { | 1108 | if (tf_start_inference(request) != DNN_SUCCESS) { |
| 1101 | goto err; | 1109 | goto err; |