From 9c695765dd7160c0a808eacd9ef3b285a67f80d2 Mon Sep 17 00:00:00 2001 From: leiradel Date: Wed, 31 Jan 2018 21:10:08 +0000 Subject: [PATCH] Fixed crash when a content is loaded before the cheevos task for the previous content was finished --- cheevos/cheevos.c | 51 ++++++++++++++++++++++++++++++++++------------- cheevos/coro.h | 5 +++++ 2 files changed, 42 insertions(+), 14 deletions(-) diff --git a/cheevos/cheevos.c b/cheevos/cheevos.c index e4b9de2b23..425577807e 100644 --- a/cheevos/cheevos.c +++ b/cheevos/cheevos.c @@ -2488,11 +2488,25 @@ bool cheevos_apply_cheats(bool *data_bool) bool cheevos_unload(void) { CHEEVOS_LOCK(cheevos_locals.task_lock); + bool running = cheevos_locals.task != NULL; + CHEEVOS_UNLOCK(cheevos_locals.task_lock); - if (cheevos_locals.task) + if (running) { +#ifdef CHEEVOS_VERBOSE + RARCH_LOG("[CHEEVOS]: Asked the load thread to terminate\n"); +#endif task_queue_cancel_task(cheevos_locals.task); - while (cheevos_locals.task) /* nothing */; + +#ifdef HAVE_THREADS + do + { + CHEEVOS_LOCK(cheevos_locals.task_lock); + running = cheevos_locals.task != NULL; + CHEEVOS_UNLOCK(cheevos_locals.task_lock); + } + while (running); +#endif } if (cheevos_loaded) @@ -2501,8 +2515,6 @@ bool cheevos_unload(void) cheevos_free_cheevo_set(&cheevos_locals.unofficial); } - CHEEVOS_UNLOCK(cheevos_locals.task_lock); - cheevos_locals.core.cheevos = NULL; cheevos_locals.unofficial.cheevos = NULL; cheevos_locals.core.count = 0; @@ -2907,7 +2919,7 @@ static int cheevos_iterate(coro_t *coro) * But set the above anyways, * command_read_ram needs it. */ if (!coro->settings->bools.cheevos_enable) - return 0; + CORO_STOP(); /* Load the content into memory, or copy it * over to our own buffer */ @@ -2919,7 +2931,7 @@ static int cheevos_iterate(coro_t *coro) RETRO_VFS_FILE_ACCESS_HINT_NONE); if (!coro->stream) - return 0; + CORO_STOP(); CORO_YIELD(); coro->len = 0; @@ -2935,7 +2947,7 @@ static int cheevos_iterate(coro_t *coro) { intfstream_close(coro->stream); free(coro->stream); - return 0; + CORO_STOP(); } for (;;) @@ -3036,7 +3048,7 @@ static int cheevos_iterate(coro_t *coro) } RARCH_LOG("[CHEEVOS]: this game doesn't feature achievements.\n"); - return 0; + CORO_STOP(); found: @@ -3062,7 +3074,7 @@ found: { runloop_msg_queue_push("Error loading achievements.", 0, 5 * 60, false); RARCH_ERR("[CHEEVOS]: error loading achievements.\n"); - return 0; + CORO_STOP(); } #endif @@ -3077,7 +3089,7 @@ found: { if ((void*)coro->json) free((void*)coro->json); - return 0; + CORO_STOP(); } if ((void*)coro->json) @@ -3132,7 +3144,7 @@ found: cheevos_unload(); CORO_GOSUB(GET_BADGES); - return 0; + CORO_STOP(); /************************************************************************** * Info Tries to identify a SNES game @@ -3434,7 +3446,7 @@ found: if (!coro->json) { RARCH_ERR("[CHEEVOS]: error getting achievements for game id %u.\n", coro->gameid); - return 0; + CORO_STOP(); } RARCH_LOG("[CHEEVOS]: got achievements for game id %u.\n", coro->gameid); @@ -3538,7 +3550,7 @@ found: "Please fill in your account information in Settings.", 0, 5 * 60, false); RARCH_ERR("[CHEEVOS]: username and/or password not informed.\n"); - return 0; + CORO_STOP(); } cheevos_url_encode(username, urle_user, sizeof(urle_user)); @@ -3588,7 +3600,7 @@ found: runloop_msg_queue_push("Retro Achievements login error.", 0, 5 * 60, false); RARCH_ERR("[CHEEVOS]: error getting user token.\n"); - return 0; + CORO_STOP(); /************************************************************************** * Info Pauses execution for five seconds @@ -3806,6 +3818,17 @@ static void cheevos_task_handler(retro_task_t *task) cheevos_locals.task = NULL; CHEEVOS_UNLOCK(cheevos_locals.task_lock); +#ifdef CHEEVOS_VERBOSE + if (task_get_cancelled(task)) + { + RARCH_LOG("[CHEEVOS]: Load task cancelled\n"); + } + else + { + RARCH_LOG("[CHEEVOS]: Load task finished\n"); + } +#endif + if (coro->data) free(coro->data); diff --git a/cheevos/coro.h b/cheevos/coro.h index 51d3e50a23..e30616b5f2 100644 --- a/cheevos/coro.h +++ b/cheevos/coro.h @@ -62,6 +62,11 @@ Released under the CC0: https://creativecommons.org/publicdomain/zero/1.0/ coro->sp = 0; \ } while ( 0 ) +#define CORO_STOP() \ + do { \ + return 0; \ + } while ( 0 ) + /* Add this macro to your coro_t structure containing the variables for the coroutine */ #define CORO_FIELDS \ int step, sp; \