Fix the race in data_finished() and resp_finished() 70/283570/1 accepted/tools_devbase_tools_legacy accepted/tools/devbase/tools/legacy/20240422.110856 accepted/tools/devbase/tools/legacy/20240423.040731 accepted/tools/devbase/tools/legacy/20240424.050712
authorMateusz Moscicki <m.moscicki2@partner.samsung.com>
Thu, 27 Oct 2022 17:53:27 +0000 (19:53 +0200)
committerSeung-Woo Kim <sw0312.kim@samsung.com>
Mon, 31 Oct 2022 00:59:42 +0000 (00:59 +0000)
Setting the data_finished and resp_finished flags too early sometimes
led to a situation in which another chunk was sent, even though the
functions had not finished executing, which resulted in a flashing
error.

For example:
When data_finished() was called, the flag data_finished was set. Then
after entering aio_error/aio_return the thread would be put to sleep and
the program would start executing the resp_finished() function. The
function was executed to the end and because data_finished flag was set,
the check_next_chunk() was called.
After that, the thread with data_finished() would return from sleep and
continue its execution, even though the data it was pointing to at that
moment is out of date. This led, among other things, to a mismatch
between numbers of chunk and the response.

Change-Id: I404b3723cb9e671d13221bff2b7823f1fdc43906
Signed-off-by: Mateusz Moscicki <m.moscicki2@samsung.com>
(cherry picked from commit 400428531184493e9d025af29286d071f84c1115)

libthor/thor_net.c

index 29cb295..9da314c 100644 (file)
@@ -242,8 +242,6 @@ static void data_finished(sigval_t sigval)
        struct t_thor_net_transfer *transfer = chunk->user_data;
        int ret;
 
-       chunk->data_finished = 1;
-
        ret = aio_error(&chunk->data_transfer);
        if (ret == ECANCELED || transfer->ret) {
                return;
@@ -260,6 +258,7 @@ static void data_finished(sigval_t sigval)
                return;
        }
 
+       chunk->data_finished = 1;
        if (chunk->resp_finished)
                check_next_chunk(chunk, transfer);
 }
@@ -270,7 +269,6 @@ static void resp_finished(sigval_t sigval)
        struct t_thor_net_transfer *transfer = chunk->user_data;
        int ret;
 
-       chunk->resp_finished = 1;
        transfer->data_in_progress -= chunk->useful_size;
 
        ret = aio_error(&chunk->resp_transfer);
@@ -309,6 +307,7 @@ static void resp_finished(sigval_t sigval)
                                          chunk->chunk_number,
                                          transfer->user_data);
 
+       chunk->resp_finished = 1;
        if (chunk->data_finished)
                check_next_chunk(chunk, transfer);
 }