From: Matthew Barnes Date: Sat, 9 Feb 2013 15:37:31 +0000 (-0500) Subject: EBookClient: Use g_bus_watch_name_on_connection(). X-Git-Tag: upstream/3.7.91~194 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=8726e44eac95b7966061d5bada845160a8ecc464;p=platform%2Fupstream%2Fevolution-data-server.git EBookClient: Use g_bus_watch_name_on_connection(). g_bus_watch_name_on_connection() handles "NameOwnerChanged" signals as well as "closed" signals from the GDBusConnection. In the event the bus name vanishes, we schedule an idle callback on the client's GMainContext to emit a "backend-died" signal. Also while we're at it, call the close() method asynchronously from dispose() so we don't block. --- diff --git a/addressbook/libebook/e-book-client.c b/addressbook/libebook/e-book-client.c index 79ff390..f13c623 100644 --- a/addressbook/libebook/e-book-client.c +++ b/addressbook/libebook/e-book-client.c @@ -51,9 +51,9 @@ typedef struct _ConnectClosure ConnectClosure; typedef struct _RunInThreadClosure RunInThreadClosure; struct _EBookClientPrivate { - EDBusAddressBook *dbus_proxy; GMainContext *main_context; - guint gone_signal_id; + EDBusAddressBook *dbus_proxy; + guint name_watcher_id; gulong dbus_proxy_error_handler_id; gulong dbus_proxy_notify_handler_id; @@ -285,87 +285,46 @@ set_proxy_gone_error (GError **error) } static volatile gint active_book_clients = 0; -static guint book_connection_closed_id = 0; +static guint book_factory_watcher_id = 0; static EDBusAddressBookFactory *book_factory = NULL; static GRecMutex book_factory_lock; #define LOCK_FACTORY() g_rec_mutex_lock (&book_factory_lock) #define UNLOCK_FACTORY() g_rec_mutex_unlock (&book_factory_lock) -static void gdbus_book_factory_closed_cb (GDBusConnection *connection, gboolean remote_peer_vanished, GError *error, gpointer user_data); - static void -gdbus_book_factory_disconnect (GDBusConnection *connection) +book_factory_disconnect (void) { LOCK_FACTORY (); - if (!connection && book_factory) - connection = g_dbus_proxy_get_connection (G_DBUS_PROXY (book_factory)); - - if (connection && book_connection_closed_id) { - g_dbus_connection_signal_unsubscribe (connection, book_connection_closed_id); - g_signal_handlers_disconnect_by_func (connection, gdbus_book_factory_closed_cb, NULL); + if (book_factory_watcher_id > 0) { + g_bus_unwatch_name (book_factory_watcher_id); + book_factory_watcher_id = 0; } - if (book_factory != NULL) - g_object_unref (book_factory); - - book_connection_closed_id = 0; - book_factory = NULL; + g_clear_object (&book_factory); UNLOCK_FACTORY (); } static void -gdbus_book_factory_closed_cb (GDBusConnection *connection, - gboolean remote_peer_vanished, - GError *error, - gpointer user_data) -{ - GError *err = NULL; - - LOCK_FACTORY (); - - gdbus_book_factory_disconnect (connection); - - if (error) - unwrap_dbus_error (g_error_copy (error), &err); - - if (err) { - g_debug ("GDBus connection is closed%s: %s", remote_peer_vanished ? ", remote peer vanished" : "", err->message); - g_error_free (err); - } else if (active_book_clients > 0) { - g_debug ("GDBus connection is closed%s", remote_peer_vanished ? ", remote peer vanished" : ""); - } - - UNLOCK_FACTORY (); -} - -static void -gdbus_book_factory_connection_gone_cb (GDBusConnection *connection, - const gchar *sender_name, - const gchar *object_path, - const gchar *interface_name, - const gchar *signal_name, - GVariant *parameters, - gpointer user_data) +book_factory_name_vanished_cb (GDBusConnection *connection, + const gchar *name, + gpointer user_data) { - /* signal subscription takes care of correct parameters, - * thus just do what is to be done here */ - gdbus_book_factory_closed_cb (connection, TRUE, NULL, user_data); + book_factory_disconnect (); } static gboolean -gdbus_book_factory_activate (GCancellable *cancellable, - GError **error) +book_factory_activate (GCancellable *cancellable, + GError **error) { - GDBusConnection *connection; + GDBusProxy *proxy; + gboolean success = TRUE; LOCK_FACTORY (); - if (G_LIKELY (book_factory != NULL)) { - UNLOCK_FACTORY (); - return TRUE; - } + if (G_LIKELY (book_factory != NULL)) + goto exit; book_factory = e_dbus_address_book_factory_proxy_new_for_bus_sync ( G_BUS_TYPE_SESSION, @@ -375,28 +334,24 @@ gdbus_book_factory_activate (GCancellable *cancellable, cancellable, error); if (book_factory == NULL) { - UNLOCK_FACTORY (); - return FALSE; + success = FALSE; + goto exit; } - connection = g_dbus_proxy_get_connection (G_DBUS_PROXY (book_factory)); - book_connection_closed_id = g_dbus_connection_signal_subscribe ( - connection, - NULL, /* sender */ - "org.freedesktop.DBus", /* interface */ - "NameOwnerChanged", /* member */ - "/org/freedesktop/DBus", /* object_path */ - "org.gnome.evolution.dataserver.AddressBook", /* arg0 */ - G_DBUS_SIGNAL_FLAGS_NONE, - gdbus_book_factory_connection_gone_cb, NULL, NULL); - - g_signal_connect ( - connection, "closed", - G_CALLBACK (gdbus_book_factory_closed_cb), NULL); + proxy = G_DBUS_PROXY (book_factory); + + book_factory_watcher_id = g_bus_watch_name_on_connection ( + g_dbus_proxy_get_connection (proxy), + g_dbus_proxy_get_name (proxy), + G_BUS_NAME_WATCHER_FLAGS_NONE, + (GBusNameAppearedCallback) NULL, + (GBusNameVanishedCallback) book_factory_name_vanished_cb, + NULL, (GDestroyNotify) NULL); +exit: UNLOCK_FACTORY (); - return TRUE; + return success; } static gpointer @@ -500,72 +455,16 @@ book_client_run_in_dbus_thread (GSimpleAsyncResult *simple, g_main_context_unref (main_context); } -static void gdbus_book_client_disconnect (EBookClient *client); - -/* - * Called when the addressbook server dies. - */ -static void -gdbus_book_client_closed_cb (GDBusConnection *connection, - gboolean remote_peer_vanished, - GError *error, - EBookClient *client) -{ - GError *err = NULL; - - g_assert (E_IS_BOOK_CLIENT (client)); - - if (error) - unwrap_dbus_error (g_error_copy (error), &err); - - if (err) { - g_debug (G_STRLOC ": EBookClient GDBus connection is closed%s: %s", remote_peer_vanished ? ", remote peer vanished" : "", err->message); - g_error_free (err); - } else { - g_debug (G_STRLOC ": EBookClient GDBus connection is closed%s", remote_peer_vanished ? ", remote peer vanished" : ""); - } - - gdbus_book_client_disconnect (client); - - e_client_emit_backend_died (E_CLIENT (client)); -} - -static void -gdbus_book_client_connection_gone_cb (GDBusConnection *connection, - const gchar *sender_name, - const gchar *object_path, - const gchar *interface_name, - const gchar *signal_name, - GVariant *parameters, - gpointer user_data) -{ - /* signal subscription takes care of correct parameters, - * thus just do what is to be done here */ - gdbus_book_client_closed_cb (connection, TRUE, NULL, user_data); -} - -static void -gdbus_book_client_disconnect (EBookClient *client) +static gboolean +book_client_emit_backend_died_idle_cb (gpointer user_data) { - g_return_if_fail (E_IS_BOOK_CLIENT (client)); - - /* Ensure that everything relevant is NULL */ - LOCK_FACTORY (); - - if (client->priv->dbus_proxy != NULL) { - GDBusConnection *connection = g_dbus_proxy_get_connection (G_DBUS_PROXY (client->priv->dbus_proxy)); - - g_signal_handlers_disconnect_by_func (connection, gdbus_book_client_closed_cb, client); - g_dbus_connection_signal_unsubscribe (connection, client->priv->gone_signal_id); - client->priv->gone_signal_id = 0; + SignalClosure *signal_closure = user_data; - e_dbus_address_book_call_close_sync ( - client->priv->dbus_proxy, NULL, NULL); - g_object_unref (client->priv->dbus_proxy); - client->priv->dbus_proxy = NULL; - } + g_signal_emit_by_name ( + signal_closure->client, + "backend-died"); - UNLOCK_FACTORY (); + return FALSE; } static gboolean @@ -703,6 +602,43 @@ book_client_dbus_proxy_notify_cb (EDBusAddressBook *dbus_proxy, } static void +book_client_name_vanished_cb (GDBusConnection *connection, + const gchar *name, + EBookClient *book_client) +{ + GSource *idle_source; + SignalClosure *signal_closure; + + signal_closure = g_slice_new0 (SignalClosure); + signal_closure->client = g_object_ref (book_client); + + idle_source = g_idle_source_new (); + g_source_set_callback ( + idle_source, + book_client_emit_backend_died_idle_cb, + signal_closure, + (GDestroyNotify) signal_closure_free); + g_source_attach (idle_source, book_client->priv->main_context); + g_source_unref (idle_source); +} + +static void +book_client_close_cb (GObject *source_object, + GAsyncResult *result, + gpointer user_data) +{ + GError *error = NULL; + + e_dbus_address_book_call_close_finish ( + E_DBUS_ADDRESS_BOOK (source_object), result, &error); + + if (error != NULL) { + g_warning ("%s: %s", G_STRFUNC, error->message); + g_error_free (error); + } +} + +static void book_client_dispose (GObject *object) { EBookClientPrivate *priv; @@ -725,7 +661,15 @@ book_client_dispose (GObject *object) priv->dbus_proxy_notify_handler_id = 0; } - gdbus_book_client_disconnect (E_BOOK_CLIENT (object)); + if (priv->dbus_proxy != NULL) { + /* Call close() asynchronously + * so we don't block dispose(). */ + e_dbus_address_book_call_close ( + priv->dbus_proxy, NULL, + book_client_close_cb, NULL); + g_object_unref (priv->dbus_proxy); + priv->dbus_proxy = NULL; + } if (priv->main_context != NULL) { g_main_context_unref (priv->main_context); @@ -739,11 +683,18 @@ book_client_dispose (GObject *object) static void book_client_finalize (GObject *object) { + EBookClientPrivate *priv; + + priv = E_BOOK_CLIENT_GET_PRIVATE (object); + + if (priv->name_watcher_id > 0) + g_bus_unwatch_name (priv->name_watcher_id); + /* Chain up to parent's finalize() method. */ G_OBJECT_CLASS (e_book_client_parent_class)->finalize (object); if (g_atomic_int_dec_and_test (&active_book_clients)) - gdbus_book_factory_disconnect (NULL); + book_factory_disconnect (); } static GDBusProxy * @@ -916,7 +867,8 @@ book_client_init_in_dbus_thread (GSimpleAsyncResult *simple, EBookClientPrivate *priv; EClient *client; ESource *source; - GDBusConnection *connection; + GDBusProxy *factory_proxy; + GDBusProxy *proxy; const gchar *uid; gchar *object_path = NULL; gulong handler_id; @@ -928,9 +880,7 @@ book_client_init_in_dbus_thread (GSimpleAsyncResult *simple, source = e_client_get_source (client); uid = e_source_get_uid (source); - LOCK_FACTORY (); - gdbus_book_factory_activate (cancellable, &error); - UNLOCK_FACTORY (); + book_factory_activate (cancellable, &error); if (error != NULL) { unwrap_dbus_error (error, &error); @@ -946,20 +896,19 @@ book_client_init_in_dbus_thread (GSimpleAsyncResult *simple, ((object_path != NULL) && (error == NULL)) || ((object_path == NULL) && (error != NULL))); - if (object_path == NULL) { + if (error != NULL) { unwrap_dbus_error (error, &error); g_simple_async_result_take_error (simple, error); return; } - connection = g_dbus_proxy_get_connection (G_DBUS_PROXY (book_factory)); + factory_proxy = G_DBUS_PROXY (book_factory); priv->dbus_proxy = e_dbus_address_book_proxy_new_sync ( - connection, + g_dbus_proxy_get_connection (factory_proxy), G_DBUS_PROXY_FLAGS_NONE, - ADDRESS_BOOK_DBUS_SERVICE_NAME, - object_path, - cancellable, &error); + g_dbus_proxy_get_name (factory_proxy), + object_path, cancellable, &error); g_free (object_path); @@ -974,39 +923,36 @@ book_client_init_in_dbus_thread (GSimpleAsyncResult *simple, return; } - g_dbus_proxy_set_default_timeout ( - G_DBUS_PROXY (priv->dbus_proxy), DBUS_PROXY_TIMEOUT_MS); + /* Configure our new GDBusProxy. */ + + proxy = G_DBUS_PROXY (priv->dbus_proxy); - priv->gone_signal_id = g_dbus_connection_signal_subscribe ( - connection, - "org.freedesktop.DBus", /* sender */ - "org.freedesktop.DBus", /* interface */ - "NameOwnerChanged", /* member */ - "/org/freedesktop/DBus", /* object_path */ - "org.gnome.evolution.dataserver.AddressBook", /* arg0 */ - G_DBUS_SIGNAL_FLAGS_NONE, - gdbus_book_client_connection_gone_cb, client, NULL); + g_dbus_proxy_set_default_timeout (proxy, DBUS_PROXY_TIMEOUT_MS); - g_signal_connect ( - connection, "closed", - G_CALLBACK (gdbus_book_client_closed_cb), client); + priv->name_watcher_id = g_bus_watch_name_on_connection ( + g_dbus_proxy_get_connection (proxy), + g_dbus_proxy_get_name (proxy), + G_BUS_NAME_WATCHER_FLAGS_NONE, + (GBusNameAppearedCallback) NULL, + (GBusNameVanishedCallback) book_client_name_vanished_cb, + client, (GDestroyNotify) NULL); handler_id = g_signal_connect_object ( - priv->dbus_proxy, "error", + proxy, "error", G_CALLBACK (book_client_dbus_proxy_error_cb), client, 0); priv->dbus_proxy_error_handler_id = handler_id; handler_id = g_signal_connect_object ( - priv->dbus_proxy, "notify", + proxy, "notify", G_CALLBACK (book_client_dbus_proxy_notify_cb), client, 0); priv->dbus_proxy_notify_handler_id = handler_id; /* Initialize our public-facing GObject properties. */ - g_object_notify (G_OBJECT (priv->dbus_proxy), "online"); - g_object_notify (G_OBJECT (priv->dbus_proxy), "writable"); - g_object_notify (G_OBJECT (priv->dbus_proxy), "capabilities"); + g_object_notify (G_OBJECT (proxy), "online"); + g_object_notify (G_OBJECT (proxy), "writable"); + g_object_notify (G_OBJECT (proxy), "capabilities"); } static gboolean