[gnome-software/gnome-40: 2/4] gs-plugin-loader: Add option to propagate error to the caller
- From: Milan Crha <mcrha src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-software/gnome-40: 2/4] gs-plugin-loader: Add option to propagate error to the caller
- Date: Tue, 1 Jun 2021 10:25:17 +0000 (UTC)
commit 59b5aaa611dae442d44b18295e37a21b69c8f48b
Author: Milan Crha <mcrha redhat com>
Date: Tue May 18 12:13:14 2021 +0200
gs-plugin-loader: Add option to propagate error to the caller
This is required on installation of the apps, when they are invoked
through D-Bus and the caller is awaiting a response. Without it
the plugin loaded hides the real error and the callers receives
success, even if the install failed or had been cancelled.
Closes https://gitlab.gnome.org/GNOME/gnome-software/-/issues/1235
lib/gs-plugin-job-private.h | 1 +
lib/gs-plugin-job.c | 29 +++++++++++++++++++++++++++++
lib/gs-plugin-job.h | 2 ++
lib/gs-plugin-loader.c | 15 +++++++++++----
lib/gs-plugin-loader.h | 2 ++
src/gs-page.c | 30 +++++++++++++++++++++++-------
6 files changed, 68 insertions(+), 11 deletions(-)
---
diff --git a/lib/gs-plugin-job-private.h b/lib/gs-plugin-job-private.h
index 863d89014..997cc8353 100644
--- a/lib/gs-plugin-job-private.h
+++ b/lib/gs-plugin-job-private.h
@@ -25,6 +25,7 @@ void gs_plugin_job_add_refine_flags (GsPluginJob *self,
void gs_plugin_job_remove_refine_flags (GsPluginJob *self,
GsPluginRefineFlags refine_flags);
gboolean gs_plugin_job_get_interactive (GsPluginJob *self);
+gboolean gs_plugin_job_get_propagate_error (GsPluginJob *self);
guint gs_plugin_job_get_max_results (GsPluginJob *self);
guint gs_plugin_job_get_timeout (GsPluginJob *self);
guint64 gs_plugin_job_get_age (GsPluginJob *self);
diff --git a/lib/gs-plugin-job.c b/lib/gs-plugin-job.c
index 4e00e4f48..7625f2c5a 100644
--- a/lib/gs-plugin-job.c
+++ b/lib/gs-plugin-job.c
@@ -22,6 +22,7 @@ struct _GsPluginJob
GsPluginRefineFlags filter_flags;
GsAppListFilterFlags dedupe_flags;
gboolean interactive;
+ gboolean propagate_error;
guint max_results;
guint timeout;
guint64 age;
@@ -54,6 +55,7 @@ enum {
PROP_REVIEW,
PROP_MAX_RESULTS,
PROP_TIMEOUT,
+ PROP_PROPAGATE_ERROR,
PROP_LAST
};
@@ -82,6 +84,8 @@ gs_plugin_job_to_string (GsPluginJob *self)
}
if (self->interactive)
g_string_append_printf (str, " with interactive=True");
+ if (self->propagate_error)
+ g_string_append_printf (str, " with propagate-error=True");
if (self->timeout > 0)
g_string_append_printf (str, " with timeout=%u", self->timeout);
if (self->max_results > 0)
@@ -212,6 +216,20 @@ gs_plugin_job_get_interactive (GsPluginJob *self)
return self->interactive;
}
+void
+gs_plugin_job_set_propagate_error (GsPluginJob *self, gboolean propagate_error)
+{
+ g_return_if_fail (GS_IS_PLUGIN_JOB (self));
+ self->propagate_error = propagate_error;
+}
+
+gboolean
+gs_plugin_job_get_propagate_error (GsPluginJob *self)
+{
+ g_return_val_if_fail (GS_IS_PLUGIN_JOB (self), FALSE);
+ return self->propagate_error;
+}
+
void
gs_plugin_job_set_max_results (GsPluginJob *self, guint max_results)
{
@@ -449,6 +467,9 @@ gs_plugin_job_get_property (GObject *obj, guint prop_id, GValue *value, GParamSp
case PROP_TIMEOUT:
g_value_set_uint (value, self->timeout);
break;
+ case PROP_PROPAGATE_ERROR:
+ g_value_set_boolean (value, self->propagate_error);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
break;
@@ -503,6 +524,9 @@ gs_plugin_job_set_property (GObject *obj, guint prop_id, const GValue *value, GP
case PROP_TIMEOUT:
gs_plugin_job_set_timeout (self, g_value_get_uint (value));
break;
+ case PROP_PROPAGATE_ERROR:
+ gs_plugin_job_set_propagate_error (self, g_value_get_boolean (value));
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
break;
@@ -602,6 +626,11 @@ gs_plugin_job_class_init (GsPluginJobClass *klass)
0, G_MAXUINT, 60,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT);
g_object_class_install_property (object_class, PROP_TIMEOUT, pspec);
+
+ pspec = g_param_spec_boolean ("propagate-error", NULL, NULL,
+ FALSE,
+ G_PARAM_READWRITE);
+ g_object_class_install_property (object_class, PROP_PROPAGATE_ERROR, pspec);
}
static void
diff --git a/lib/gs-plugin-job.h b/lib/gs-plugin-job.h
index 885be1c8c..4bd7b6249 100644
--- a/lib/gs-plugin-job.h
+++ b/lib/gs-plugin-job.h
@@ -28,6 +28,8 @@ void gs_plugin_job_set_dedupe_flags (GsPluginJob *self,
GsAppListFilterFlags dedupe_flags);
void gs_plugin_job_set_interactive (GsPluginJob *self,
gboolean interactive);
+void gs_plugin_job_set_propagate_error (GsPluginJob *self,
+ gboolean propagate_error);
void gs_plugin_job_set_max_results (GsPluginJob *self,
guint max_results);
void gs_plugin_job_set_timeout (GsPluginJob *self,
diff --git a/lib/gs-plugin-loader.c b/lib/gs-plugin-loader.c
index 0543f40d9..20f9ab440 100644
--- a/lib/gs-plugin-loader.c
+++ b/lib/gs-plugin-loader.c
@@ -316,7 +316,7 @@ gs_plugin_loader_notify_idle_cb (gpointer user_data)
return FALSE;
}
-static void
+void
gs_plugin_loader_add_event (GsPluginLoader *plugin_loader, GsPluginEvent *event)
{
g_autoptr(GMutexLocker) locker = g_mutex_locker_new (&plugin_loader->events_by_id_mutex);
@@ -400,6 +400,11 @@ gs_plugin_error_handle_failure (GsPluginLoaderHelper *helper,
return TRUE;
}
+ if (gs_plugin_job_get_propagate_error (helper->plugin_job)) {
+ g_propagate_error (error, g_error_copy (error_local));
+ return FALSE;
+ }
+
/* this is only ever informational */
if (g_error_matches (error_local, GS_PLUGIN_ERROR, GS_PLUGIN_ERROR_CANCELLED) ||
g_error_matches (error_local, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
@@ -3421,13 +3426,15 @@ gs_plugin_loader_process_thread_cb (GTask *task,
if (gs_app_list_length (list) == 0) {
g_autofree gchar *str = gs_plugin_job_to_string (helper->plugin_job);
g_autoptr(GError) error_local = NULL;
- g_autoptr(GsPluginEvent) event = NULL;
g_set_error (&error_local,
GS_PLUGIN_ERROR,
GS_PLUGIN_ERROR_NOT_SUPPORTED,
"no application was created for %s", str);
- event = gs_plugin_job_to_failed_event (helper->plugin_job, error_local);
- gs_plugin_loader_add_event (plugin_loader, event);
+ if (!gs_plugin_job_get_propagate_error (helper->plugin_job)) {
+ g_autoptr(GsPluginEvent) event = NULL;
+ event = gs_plugin_job_to_failed_event (helper->plugin_job, error_local);
+ gs_plugin_loader_add_event (plugin_loader, event);
+ }
g_task_return_error (task, g_steal_pointer (&error_local));
return;
}
diff --git a/lib/gs-plugin-loader.h b/lib/gs-plugin-loader.h
index 056067bd8..4b76d9ebb 100644
--- a/lib/gs-plugin-loader.h
+++ b/lib/gs-plugin-loader.h
@@ -63,6 +63,8 @@ gboolean gs_plugin_loader_get_network_metered (GsPluginLoader *plugin_loader);
gboolean gs_plugin_loader_get_plugin_supported (GsPluginLoader *plugin_loader,
const gchar *function_name);
+void gs_plugin_loader_add_event (GsPluginLoader *plugin_loader,
+ GsPluginEvent *event);
GPtrArray *gs_plugin_loader_get_events (GsPluginLoader *plugin_loader);
GsPluginEvent *gs_plugin_loader_get_event_default (GsPluginLoader *plugin_loader);
void gs_plugin_loader_remove_events (GsPluginLoader *plugin_loader);
diff --git a/src/gs-page.c b/src/gs-page.c
index 87effb97f..678da7798 100644
--- a/src/gs-page.c
+++ b/src/gs-page.c
@@ -43,6 +43,7 @@ typedef struct {
GtkWidget *button_install;
GsPluginAction action;
GsShellInteraction interaction;
+ gboolean propagate_error;
} GsPageHelper;
static void
@@ -131,16 +132,29 @@ gs_page_app_installed_cb (GObject *source,
gs_application_emit_install_resources_done (GS_APPLICATION (g_application_get_default ()), NULL,
error);
- if (g_error_matches (error,
- GS_PLUGIN_ERROR,
- GS_PLUGIN_ERROR_CANCELLED)) {
- g_debug ("%s", error->message);
+ if (g_error_matches (error, GS_PLUGIN_ERROR, GS_PLUGIN_ERROR_CANCELLED) ||
+ g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
+ g_debug ("App install cancelled with error: %s", error->message);
return;
}
if (!ret) {
- g_warning ("failed to install %s: %s",
- gs_app_get_id (helper->app),
- error->message);
+ if (helper->propagate_error) {
+ g_autoptr(GsPluginEvent) event = NULL;
+
+ /* create event which is handled by the GsShell */
+ event = gs_plugin_event_new ();
+ gs_plugin_event_set_error (event, error);
+ gs_plugin_event_set_action (event, helper->action);
+ gs_plugin_event_set_app (event, helper->app);
+ if (helper->interaction == GS_SHELL_INTERACTION_FULL)
+ gs_plugin_event_add_flag (event, GS_PLUGIN_EVENT_FLAG_INTERACTIVE);
+ gs_plugin_event_add_flag (event, GS_PLUGIN_EVENT_FLAG_WARNING);
+
+ /* add event to queue */
+ gs_plugin_loader_add_event (plugin_loader, event);
+ } else {
+ g_warning ("failed to install %s: %s", gs_app_get_id (helper->app), error->message);
+ }
return;
}
@@ -260,9 +274,11 @@ gs_page_install_app (GsPage *page,
helper->page = g_object_ref (page);
helper->cancellable = g_object_ref (cancellable);
helper->interaction = interaction;
+ helper->propagate_error = TRUE;
plugin_job = gs_plugin_job_newv (helper->action,
"interactive", (interaction == GS_SHELL_INTERACTION_FULL),
+ "propagate-error", helper->propagate_error,
"app", helper->app,
NULL);
gs_plugin_loader_job_process_async (priv->plugin_loader,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]