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.
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; |