[gnome-software] gs-plugin-loader: Do not return a valid result if the job is cancelled



commit d88d63b253c98723aeeca8ff7852668bb221cc24
Author: Andre Moreira Magalhaes <andre endlessm com>
Date:   Wed Oct 30 16:25:30 2019 -0300

    gs-plugin-loader: Do not return a valid result if the job is cancelled
    
    This fixes an issue when switching categories in a quick succession
    where gs_plugin_loader_job_process_async() is invoked for a category,
    then gets cancelled before completing when the category is changed but
    the thread running the initial job still returns a valid result, which
    then confuses GsCategoryPage which ends up re-adding the items.

 lib/gs-plugin-loader.c | 23 ++++++++++++++++++++++-
 1 file changed, 22 insertions(+), 1 deletion(-)
---
diff --git a/lib/gs-plugin-loader.c b/lib/gs-plugin-loader.c
index 8fef5f22..5209b70f 100644
--- a/lib/gs-plugin-loader.c
+++ b/lib/gs-plugin-loader.c
@@ -1402,6 +1402,7 @@ gs_plugin_loader_job_process_finish (GsPluginLoader *plugin_loader,
                                     GAsyncResult *res,
                                     GError **error)
 {
+       GTask *task;
        GsAppList *list = NULL;
 
        g_return_val_if_fail (GS_IS_PLUGIN_LOADER (plugin_loader), NULL);
@@ -1409,7 +1410,27 @@ gs_plugin_loader_job_process_finish (GsPluginLoader *plugin_loader,
        g_return_val_if_fail (g_task_is_valid (res, plugin_loader), NULL);
        g_return_val_if_fail (error == NULL || *error == NULL, NULL);
 
-       list = g_task_propagate_pointer (G_TASK (res), error);
+       task = G_TASK (res);
+
+       /* Return cancelled if the task was cancelled and there is no other error set.
+        *
+        * This is needed because we set the task `check_cancellable` to FALSE,
+        * to be able to catch other errors such as timeout, but that means
+        * g_task_propagate_pointer() will ignore if the task was cancelled and only
+        * check if there was an error (i.e. g_task_return_*error*).
+        *
+        * We only do this if there is no error already set in the task (e.g.
+        * timeout) because in that case we want to return the existing error.
+        */
+       if (!g_task_had_error (task)) {
+               GCancellable *cancellable = g_task_get_cancellable (task);
+
+               if (g_cancellable_set_error_if_cancelled (cancellable, error)) {
+                       gs_utils_error_convert_gio (error);
+                       return NULL;
+               }
+       }
+       list = g_task_propagate_pointer (task, error);
        gs_utils_error_convert_gio (error);
        return list;
 }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]