From 9547614b1c2a0c3c0cba8792123c2d0b2954aecc Mon Sep 17 00:00:00 2001 From: Marius Vollmer Date: Mon, 11 Mar 2013 15:15:05 +0200 Subject: [PATCH 3/4] Make example domain discovery cancellable. --- service/Makefile.am | 1 + service/realm-example-provider.c | 24 ++++++--- service/realm-example.c | 107 +++++---------------------------------- service/realm-usleep-async.c | 98 +++++++++++++++++++++++++++++++++++ service/realm-usleep-async.h | 38 ++++++++++++++ 5 files changed, 165 insertions(+), 103 deletions(-) create mode 100644 service/realm-usleep-async.c create mode 100644 service/realm-usleep-async.h diff --git a/service/Makefile.am b/service/Makefile.am index 647b100..00bd295 100644 --- a/service/Makefile.am +++ b/service/Makefile.am @@ -52,6 +52,7 @@ realmd_SOURCES = \ realm-sssd-provider.c realm-sssd-provider.h \ realm-sssd-config.c realm-sssd-config.h \ realm-sssd-ipa.c realm-sssd-ipa.h \ + realm-usleep-async.c realm-usleep-async.h \ $(NULL) realmd_CFLAGS = \ diff --git a/service/realm-example-provider.c b/service/realm-example-provider.c index 82df58c..1c12aea 100644 --- a/service/realm-example-provider.c +++ b/service/realm-example-provider.c @@ -24,6 +24,8 @@ #include "realm-ini-config.h" #include "realm-settings.h" #include "realm-kerberos.h" +#include "realm-usleep-async.h" +#include "realm-invocation.h" #include @@ -86,12 +88,19 @@ realm_example_provider_constructed (GObject *obj) g_strfreev (sections); } -static gboolean -on_discover_timeout (gpointer user_data) +static void +on_discover_sleep_done (GObject *source, + GAsyncResult *res, + gpointer user_data) { GSimpleAsyncResult *async = G_SIMPLE_ASYNC_RESULT (user_data); + GError *error = NULL; + + if (!realm_usleep_finish (res, &error)) + g_simple_async_result_take_error (async, error); + g_simple_async_result_complete (async); - return FALSE; + g_object_unref (async); } static gchar * @@ -178,11 +187,10 @@ realm_example_provider_discover_async (RealmProvider *provider, domain, g_free); - g_timeout_add_full (G_PRIORITY_DEFAULT, - delay * 1000, - on_discover_timeout, - g_object_ref (async), - g_object_unref); + realm_usleep_async (delay * G_USEC_PER_SEC, + realm_invocation_get_cancellable (invocation), + on_discover_sleep_done, + g_object_ref (async)); } g_object_unref (async); diff --git a/service/realm-example.c b/service/realm-example.c index cf33133..3c0c2ba 100644 --- a/service/realm-example.c +++ b/service/realm-example.c @@ -23,93 +23,10 @@ #include "realm-invocation.h" #include "realm-kerberos-membership.h" #include "realm-settings.h" +#include "realm-usleep-async.h" #include -/* A cancellable delay - */ - -typedef struct { - GSimpleAsyncResult *async; - guint timeout_id; - GCancellable *cancellable; - guint cancel_id; -} SleepAsyncData; - -static void -free_sleep_async_data (gpointer user_data) -{ - SleepAsyncData *data = user_data; - if (data->cancellable) { - /* g_cancellable_disconnect would dead-lock here - */ - g_signal_handler_disconnect (data->cancellable, data->cancel_id); - g_object_unref (data->cancellable); - } - g_object_unref (data->async); - g_free (data); -} - -static gboolean -on_sleep_async_done (gpointer user_data) -{ - SleepAsyncData *data = user_data; - g_simple_async_result_complete (data->async); - return FALSE; -} - -static void -on_sleep_async_cancelled (GCancellable *cancellable, - gpointer user_data) -{ - SleepAsyncData *data = user_data; - g_simple_async_result_complete (data->async); - g_source_remove (data->timeout_id); -} - -static void -usleep_async (gulong microseconds, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - SleepAsyncData *data = g_new0(SleepAsyncData, 1); - data->async = g_simple_async_result_new (NULL, - callback, user_data, - usleep_async); - - if (cancellable) { - data->cancellable = g_object_ref (cancellable); - data->cancel_id = g_cancellable_connect (cancellable, - G_CALLBACK (on_sleep_async_cancelled), - data, NULL); - g_simple_async_result_set_check_cancellable (data->async, cancellable); - } - - data->timeout_id = g_timeout_add_full (G_PRIORITY_DEFAULT, - microseconds / 1000, - on_sleep_async_done, - data, (GDestroyNotify)free_sleep_async_data); -} - -static gboolean -usleep_finish (GAsyncResult *result, - GError **error) -{ - GSimpleAsyncResult *simple; - - g_return_val_if_fail (g_simple_async_result_is_valid (result, - NULL, - usleep_async), - FALSE); - - simple = (GSimpleAsyncResult *) result; - if (g_simple_async_result_propagate_error (simple, error)) - return FALSE; - - return TRUE; -} - struct _RealmExample { RealmKerberos parent; RealmIniConfig *config; @@ -242,7 +159,7 @@ on_join_sleep_done (GObject *source, GError *error = NULL; const gchar *realm_name; - if (usleep_finish (res, &error)) { + if (realm_usleep_finish (res, &error)) { realm_name = realm_kerberos_get_name (REALM_KERBEROS (data->self)); realm_ini_config_change (data->self->config, realm_name, &error, "login-formats", "%U@%D", @@ -297,9 +214,9 @@ realm_example_join_async (RealmKerberosMembership *membership, OpData *data = g_new0 (OpData, 1); data->self = g_object_ref (self); data->async = g_object_ref (async); - usleep_async (settings_delay (realm_name, "example-join-delay"), - realm_invocation_get_cancellable (invocation), - on_join_sleep_done, data); + realm_usleep_async (settings_delay (realm_name, "example-join-delay"), + realm_invocation_get_cancellable (invocation), + on_join_sleep_done, data); } g_object_unref (async); @@ -314,7 +231,7 @@ on_leave_sleep_done (GObject *source, GError *error = NULL; const gchar *realm_name; - if (usleep_finish (res, &error)) { + if (realm_usleep_finish (res, &error)) { realm_name = realm_kerberos_get_name (REALM_KERBEROS (data->self)); if (realm_ini_config_begin_change (data->self->config, &error)) { @@ -384,9 +301,9 @@ realm_example_leave_password_async (RealmKerberosMembership *membership, OpData *data = g_new0 (OpData, 1); data->self = g_object_ref (self); data->async = g_object_ref (async); - usleep_async (settings_delay (realm_name, "example-leave-delay"), - realm_invocation_get_cancellable (invocation), - on_leave_sleep_done, data); + realm_usleep_async (settings_delay (realm_name, "example-leave-delay"), + realm_invocation_get_cancellable (invocation), + on_leave_sleep_done, data); } g_object_unref (async); @@ -419,9 +336,9 @@ realm_example_leave_automatic_async (RealmKerberosMembership *membership, OpData *data = g_new0 (OpData, 1); data->self = g_object_ref (self); data->async = g_object_ref (async); - usleep_async (settings_delay (realm_name, "example-leave-delay"), - realm_invocation_get_cancellable (invocation), - on_leave_sleep_done, data); + realm_usleep_async (settings_delay (realm_name, "example-leave-delay"), + realm_invocation_get_cancellable (invocation), + on_leave_sleep_done, data); } g_object_unref (async); diff --git a/service/realm-usleep-async.c b/service/realm-usleep-async.c new file mode 100644 index 0000000..72c13e2 --- /dev/null +++ b/service/realm-usleep-async.c @@ -0,0 +1,98 @@ +/* realmd -- Realm configuration service + * + * Copyright 2013 Red Hat Inc + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 2 of the licence or (at + * your option) any later version. + * + * See the included COPYING file for more information. + * + * Author: Marius Vollmer + */ + +#include "config.h" + +#include "realm-usleep-async.h" + +typedef struct { + GSimpleAsyncResult *async; + guint timeout_id; + GCancellable *cancellable; + guint cancel_id; +} SleepAsyncData; + +static void +free_sleep_async_data (gpointer user_data) +{ + SleepAsyncData *data = user_data; + if (data->cancellable) { + /* g_cancellable_disconnect would dead-lock here + */ + g_signal_handler_disconnect (data->cancellable, data->cancel_id); + g_object_unref (data->cancellable); + } + g_object_unref (data->async); + g_free (data); +} + +static gboolean +on_sleep_async_done (gpointer user_data) +{ + SleepAsyncData *data = user_data; + g_simple_async_result_complete (data->async); + return FALSE; +} + +static void +on_sleep_async_cancelled (GCancellable *cancellable, + gpointer user_data) +{ + SleepAsyncData *data = user_data; + g_simple_async_result_complete (data->async); + g_source_remove (data->timeout_id); +} + +void +realm_usleep_async (gulong microseconds, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + SleepAsyncData *data = g_new0(SleepAsyncData, 1); + data->async = g_simple_async_result_new (NULL, + callback, user_data, + realm_usleep_async); + + if (cancellable) { + data->cancellable = g_object_ref (cancellable); + data->cancel_id = g_cancellable_connect (cancellable, + G_CALLBACK (on_sleep_async_cancelled), + data, NULL); + g_simple_async_result_set_check_cancellable (data->async, cancellable); + } + + data->timeout_id = g_timeout_add_full (G_PRIORITY_DEFAULT, + microseconds / 1000, + on_sleep_async_done, + data, (GDestroyNotify)free_sleep_async_data); +} + +gboolean +realm_usleep_finish (GAsyncResult *result, + GError **error) +{ + GSimpleAsyncResult *simple; + + g_return_val_if_fail (g_simple_async_result_is_valid (result, + NULL, + realm_usleep_async), + FALSE); + + simple = (GSimpleAsyncResult *) result; + if (g_simple_async_result_propagate_error (simple, error)) + return FALSE; + + return TRUE; +} diff --git a/service/realm-usleep-async.h b/service/realm-usleep-async.h new file mode 100644 index 0000000..d19c1f7 --- /dev/null +++ b/service/realm-usleep-async.h @@ -0,0 +1,38 @@ +/* realmd -- Realm configuration service + * + * Copyright 2013 Red Hat Inc + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 2 of the licence or (at + * your option) any later version. + * + * See the included COPYING file for more information. + * + * Author: Marius Vollmer + */ + +#include "config.h" + +#ifndef __REALM_USLEEP_ASYNC_H__ +#define __REALM_USLEEP_ASYNC_H__ + +#include +#include + +G_BEGIN_DECLS + +/* A cancellable delay + */ + +void realm_usleep_async (gulong microseconds, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); + +gboolean realm_usleep_finish (GAsyncResult *result, + GError **error); + +G_END_DECLS + +#endif /* __REALM_USLEEP_ASYNC_H__ */ -- 1.8.1.4