From 37e3c0b252a10a73468ba85bb7771c4a7da5969a Mon Sep 17 00:00:00 2001 From: Victorien Le Couviour--Tuffet Date: Mon, 13 Mar 2023 13:46:43 +0100 Subject: [PATCH] threading: Ensure passing the correct retval to decode_frame_exit We must reload error just before calling dav1d_decode_frame_exit, as it may have become stale between the last load and that call. This can result in crashes since we signal a seemingly successfully decoded frame, when it's not. Reloading error within the frame done condition's body ensures a non-stale value, as we use 'f->task_thread.task_counter == 0' to ensure all other threads / tasks have already completed when entering it. In other words, only the last thread still working on this frame can execute this code, after all other threads have returned to doing something else. --- src/thread_task.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/thread_task.c b/src/thread_task.c index 9dc4ab65a..49a8c123f 100644 --- a/src/thread_task.c +++ b/src/thread_task.c @@ -793,6 +793,7 @@ void *dav1d_worker_task(void *data) { atomic_load(&f->task_thread.done[0]) && (!uses_2pass || atomic_load(&f->task_thread.done[1]))) { + error = atomic_load(&f->task_thread.error); dav1d_decode_frame_exit(f, error == 1 ? DAV1D_ERR(EINVAL) : error ? DAV1D_ERR(ENOMEM) : 0); f->n_tile_data = 0; @@ -889,6 +890,7 @@ void *dav1d_worker_task(void *data) { if (!num_tasks && atomic_load(&f->task_thread.done[0]) && atomic_load(&f->task_thread.done[1])) { + error = atomic_load(&f->task_thread.error); dav1d_decode_frame_exit(f, error == 1 ? DAV1D_ERR(EINVAL) : error ? DAV1D_ERR(ENOMEM) : 0); f->n_tile_data = 0; @@ -918,6 +920,7 @@ void *dav1d_worker_task(void *data) { if (!num_tasks && atomic_load(&f->task_thread.done[0]) && (!uses_2pass || atomic_load(&f->task_thread.done[1]))) { + error = atomic_load(&f->task_thread.error); dav1d_decode_frame_exit(f, error == 1 ? DAV1D_ERR(EINVAL) : error ? DAV1D_ERR(ENOMEM) : 0); f->n_tile_data = 0;