Properly chain-up GTasks around GDBusProxy::init_async

Our GAsyncInitable implementations in SecretService, SecretCollection,
and SecretItem internally wrap GDBusProxy::init_async and perform
additional error processing. To chain up we used to pass around a
single GTask, which caused an issue in the (additional) error path:
GDBusProxy::init_async may have already called
g_task_return_boolean(task, TRUE) and in that case GLib produces the
following warning:

  g_task_return_error: assertion '!task->ever_returned' failed

This fixes the issue by creating a temporary GTask around
GDBusProxy::init_async call.

Signed-off-by: Daiki Ueno <dueno@src.gnome.org>
This commit is contained in:
Daiki Ueno 2022-05-08 09:32:23 +02:00
parent ef2fc44363
commit d768ce4efe
3 changed files with 85 additions and 12 deletions

View File

@ -625,17 +625,35 @@ on_init_service (GObject *source,
g_clear_object (&task); g_clear_object (&task);
} }
typedef struct {
GAsyncReadyCallback callback;
gpointer user_data;
} InitBaseClosure;
static void
secret_collection_async_initable_init_async (GAsyncInitable *initable,
int io_priority,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
static void static void
on_init_base (GObject *source, on_init_base (GObject *source,
GAsyncResult *result, GAsyncResult *result,
gpointer user_data) gpointer user_data)
{ {
GTask *task = G_TASK (user_data); GTask *base_task = G_TASK (user_data);
GCancellable *cancellable = g_task_get_cancellable (task); InitBaseClosure *base = g_task_get_task_data (base_task);
GCancellable *cancellable = g_task_get_cancellable (base_task);
GTask *task;
SecretCollection *self = SECRET_COLLECTION (source); SecretCollection *self = SECRET_COLLECTION (source);
GDBusProxy *proxy = G_DBUS_PROXY (self); GDBusProxy *proxy = G_DBUS_PROXY (self);
GError *error = NULL; GError *error = NULL;
task = g_task_new (source, cancellable, base->callback, base->user_data);
g_task_set_source_tag (task, secret_collection_async_initable_init_async);
g_clear_object (&base_task);
if (!secret_collection_async_initable_parent_iface->init_finish (G_ASYNC_INITABLE (self), if (!secret_collection_async_initable_parent_iface->init_finish (G_ASYNC_INITABLE (self),
result, &error)) { result, &error)) {
g_task_return_error (task, g_steal_pointer (&error)); g_task_return_error (task, g_steal_pointer (&error));
@ -665,10 +683,16 @@ secret_collection_async_initable_init_async (GAsyncInitable *initable,
gpointer user_data) gpointer user_data)
{ {
GTask *task; GTask *task;
InitBaseClosure *base;
task = g_task_new (initable, cancellable, callback, user_data); task = g_task_new (initable, cancellable, NULL, NULL);
g_task_set_source_tag (task, secret_collection_async_initable_init_async); g_task_set_source_tag (task, secret_collection_async_initable_init_async);
base = g_new0 (InitBaseClosure, 1);
base->callback = callback;
base->user_data = user_data;
g_task_set_task_data (task, base, g_free);
secret_collection_async_initable_parent_iface->init_async (initable, secret_collection_async_initable_parent_iface->init_async (initable,
io_priority, io_priority,
cancellable, cancellable,

View File

@ -512,17 +512,35 @@ on_init_service (GObject *source,
g_clear_object (&task); g_clear_object (&task);
} }
typedef struct {
GAsyncReadyCallback callback;
gpointer user_data;
} InitBaseClosure;
static void
secret_item_async_initable_init_async (GAsyncInitable *initable,
int io_priority,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
static void static void
on_init_base (GObject *source, on_init_base (GObject *source,
GAsyncResult *result, GAsyncResult *result,
gpointer user_data) gpointer user_data)
{ {
GTask *task = G_TASK (user_data); GTask *base_task = G_TASK (user_data);
GCancellable *cancellable = g_task_get_cancellable (task); InitBaseClosure *base = g_task_get_task_data (base_task);
GCancellable *cancellable = g_task_get_cancellable (base_task);
GTask *task;
SecretItem *self = SECRET_ITEM (source); SecretItem *self = SECRET_ITEM (source);
GDBusProxy *proxy = G_DBUS_PROXY (self); GDBusProxy *proxy = G_DBUS_PROXY (self);
GError *error = NULL; GError *error = NULL;
task = g_task_new (source, cancellable, base->callback, base->user_data);
g_task_set_source_tag (task, secret_item_async_initable_init_async);
g_clear_object (&base_task);
if (!secret_item_async_initable_parent_iface->init_finish (G_ASYNC_INITABLE (self), if (!secret_item_async_initable_parent_iface->init_finish (G_ASYNC_INITABLE (self),
result, &error)) { result, &error)) {
g_task_return_error (task, g_steal_pointer (&error)); g_task_return_error (task, g_steal_pointer (&error));
@ -552,10 +570,16 @@ secret_item_async_initable_init_async (GAsyncInitable *initable,
gpointer user_data) gpointer user_data)
{ {
GTask *task; GTask *task;
InitBaseClosure *base;
task = g_task_new (initable, cancellable, callback, user_data); task = g_task_new (initable, cancellable, NULL, NULL);
g_task_set_source_tag (task, secret_item_async_initable_init_async); g_task_set_source_tag (task, secret_item_async_initable_init_async);
base = g_new0 (InitBaseClosure, 1);
base->callback = callback;
base->user_data = user_data;
g_task_set_task_data (task, base, g_free);
secret_item_async_initable_parent_iface->init_async (initable, io_priority, secret_item_async_initable_parent_iface->init_async (initable, io_priority,
cancellable, cancellable,
on_init_base, on_init_base,

View File

@ -717,18 +717,41 @@ secret_service_initable_iface (GInitableIface *iface)
iface->init = secret_service_initable_init; iface->init = secret_service_initable_init;
} }
static void
secret_service_async_initable_init_async (GAsyncInitable *initable,
int io_priority,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
typedef struct {
GAsyncReadyCallback callback;
gpointer user_data;
} InitBaseClosure;
static void static void
on_init_base (GObject *source, on_init_base (GObject *source,
GAsyncResult *result, GAsyncResult *result,
gpointer user_data) gpointer user_data)
{ {
GTask *task = G_TASK (user_data); GTask *base_task = G_TASK (user_data);
InitBaseClosure *base = g_task_get_task_data (base_task);
GCancellable *cancellable = g_task_get_cancellable (base_task);
GTask *task;
InitClosure *init;
SecretService *self = SECRET_SERVICE (source); SecretService *self = SECRET_SERVICE (source);
GError *error = NULL; GError *error = NULL;
task = g_task_new (source, cancellable, base->callback, base->user_data);
g_task_set_source_tag (task, secret_service_async_initable_init_async);
init = g_slice_new0 (InitClosure);
g_task_set_task_data (task, init, init_closure_free);
g_clear_object (&base_task);
if (!secret_service_async_initable_parent_iface->init_finish (G_ASYNC_INITABLE (self), if (!secret_service_async_initable_parent_iface->init_finish (G_ASYNC_INITABLE (self),
result, &error)) { result, &error)) {
g_task_return_error (task, error); g_task_return_error (task, g_steal_pointer (&error));
} else { } else {
service_ensure_for_flags_async (self, self->pv->init_flags, task); service_ensure_for_flags_async (self, self->pv->init_flags, task);
} }
@ -744,12 +767,14 @@ secret_service_async_initable_init_async (GAsyncInitable *initable,
gpointer user_data) gpointer user_data)
{ {
GTask *task; GTask *task;
InitClosure *closure; InitBaseClosure *base;
task = g_task_new (initable, cancellable, callback, user_data); task = g_task_new (initable, cancellable, NULL, NULL);
g_task_set_source_tag (task, secret_service_async_initable_init_async); g_task_set_source_tag (task, secret_service_async_initable_init_async);
closure = g_slice_new0 (InitClosure); base = g_new0 (InitBaseClosure, 1);
g_task_set_task_data (task, closure, init_closure_free); base->callback = callback;
base->user_data = user_data;
g_task_set_task_data (task, base, g_free);
secret_service_async_initable_parent_iface->init_async (initable, secret_service_async_initable_parent_iface->init_async (initable,
io_priority, io_priority,