[evolution-data-server] Bug #625514 - Client doesn't recognize server close/crash on GDBus
- From: Milan Crha <mcrha src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-data-server] Bug #625514 - Client doesn't recognize server close/crash on GDBus
- Date: Tue, 24 Aug 2010 09:01:57 +0000 (UTC)
commit 1f06f66257d03a15a3bc6c23d5d30eecd175850e
Author: Milan Crha <mcrha redhat com>
Date: Tue Aug 24 11:01:05 2010 +0200
Bug #625514 - Client doesn't recognize server close/crash on GDBus
addressbook/libebook/e-book.c | 56 ++++++++++++++++++++-
calendar/libecal/e-cal.c | 110 ++++++++++++++++++++++++++++++++++-------
2 files changed, 144 insertions(+), 22 deletions(-)
---
diff --git a/addressbook/libebook/e-book.c b/addressbook/libebook/e-book.c
index 1f76705..537dddc 100644
--- a/addressbook/libebook/e-book.c
+++ b/addressbook/libebook/e-book.c
@@ -69,6 +69,7 @@ static guint e_book_signals [LAST_SIGNAL];
struct _EBookPrivate {
EGdbusBook *gdbus_book;
+ guint gone_signal_id;
ESource *source;
gchar *uri;
@@ -120,6 +121,8 @@ gdbus_book_closed_cb (GDBusConnection *connection, gboolean remote_peer_vanished
if (err) {
g_debug (G_STRLOC ": EBook GDBus connection is closed%s: %s", remote_peer_vanished ? ", remote peer vanished" : "", err->message);
g_error_free (err);
+ } else {
+ g_debug (G_STRLOC ": EBook GDBus connection is closed%s", remote_peer_vanished ? ", remote peer vanished" : "");
}
/* Ensure that everything relevant is NULL */
@@ -136,6 +139,14 @@ gdbus_book_closed_cb (GDBusConnection *connection, gboolean remote_peer_vanished
}
static void
+gdbus_book_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_closed_cb (connection, TRUE, NULL, user_data);
+}
+
+static void
e_book_dispose (GObject *object)
{
EBook *book = E_BOOK (object);
@@ -143,7 +154,12 @@ e_book_dispose (GObject *object)
book->priv->loaded = FALSE;
if (book->priv->gdbus_book) {
- g_signal_handlers_disconnect_by_func (g_dbus_proxy_get_connection (G_DBUS_PROXY (book->priv->gdbus_book)), gdbus_book_closed_cb, book);
+ GDBusConnection *connection = g_dbus_proxy_get_connection (G_DBUS_PROXY (book->priv->gdbus_book));
+
+ g_signal_handlers_disconnect_by_func (connection, gdbus_book_closed_cb, book);
+ g_dbus_connection_signal_unsubscribe (connection, book->priv->gone_signal_id);
+ book->priv->gone_signal_id = 0;
+
e_gdbus_book_call_close_sync (book->priv->gdbus_book, NULL, NULL);
g_object_unref (book->priv->gdbus_book);
book->priv->gdbus_book = NULL;
@@ -255,14 +271,26 @@ book_factory_proxy_closed_cb (GDBusConnection *connection, gboolean remote_peer_
if (err) {
g_debug ("GDBus connection is closed%s: %s", remote_peer_vanished ? ", remote peer vanished" : "", err->message);
g_error_free (err);
+ } else {
+ g_debug ("GDBus connection is closed%s", remote_peer_vanished ? ", remote peer vanished" : "");
}
UNLOCK_FACTORY ();
}
+static void
+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)
+{
+ /* signal subscription takes care of correct parameters,
+ thus just do what is to be done here */
+ book_factory_proxy_closed_cb (connection, TRUE, NULL, user_data);
+}
+
static gboolean
e_book_activate (GError **error)
{
+ GDBusConnection *connection;
+
LOCK_FACTORY ();
if (G_LIKELY (book_factory_proxy)) {
@@ -283,7 +311,18 @@ e_book_activate (GError **error)
return FALSE;
}
- g_signal_connect (g_dbus_proxy_get_connection (G_DBUS_PROXY (book_factory_proxy)), "closed", G_CALLBACK (book_factory_proxy_closed_cb), NULL);
+ connection = g_dbus_proxy_get_connection (G_DBUS_PROXY (book_factory_proxy));
+ g_dbus_connection_set_exit_on_close (connection, FALSE);
+ 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,
+ book_factory_connection_gone_cb, NULL, NULL);
+
+ g_signal_connect (connection, "closed", G_CALLBACK (book_factory_proxy_closed_cb), NULL);
UNLOCK_FACTORY ();
@@ -3010,6 +3049,7 @@ e_book_new (ESource *source, GError **error)
GError *err = NULL;
EBook *book;
gchar *path, *xml;
+ GDBusConnection *connection;
e_return_error_if_fail (E_IS_SOURCE (source), E_BOOK_ERROR_INVALID_ARG);
@@ -3059,7 +3099,17 @@ e_book_new (ESource *source, GError **error)
g_free (path);
- g_signal_connect (g_dbus_proxy_get_connection (G_DBUS_PROXY (book->priv->gdbus_book)), "closed", G_CALLBACK (gdbus_book_closed_cb), book);
+ connection = g_dbus_proxy_get_connection (G_DBUS_PROXY (book->priv->gdbus_book));
+ book->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_connection_gone_cb, book, NULL);
+ g_signal_connect (connection, "closed", G_CALLBACK (gdbus_book_closed_cb), book);
+
g_signal_connect (book->priv->gdbus_book, "writable", G_CALLBACK (writable_cb), book);
g_signal_connect (book->priv->gdbus_book, "connection", G_CALLBACK (connection_cb), book);
g_signal_connect (book->priv->gdbus_book, "auth-required", G_CALLBACK (auth_required_cb), book);
diff --git a/calendar/libecal/e-cal.c b/calendar/libecal/e-cal.c
index ba02bbd..3352ad6 100644
--- a/calendar/libecal/e-cal.c
+++ b/calendar/libecal/e-cal.c
@@ -74,6 +74,9 @@ static void e_cal_finalize (GObject *object);
/* Private part of the ECal structure */
struct _ECalPrivate {
+ EGdbusCal *gdbus_cal;
+ guint gone_signal_id;
+
/* Load state to avoid multiple loads */
ECalLoadState load_state;
@@ -96,8 +99,6 @@ struct _ECalPrivate {
gboolean read_only;
- EGdbusCal *gdbus_cal;
-
/* The authentication function */
ECalAuthFunc auth_func;
gpointer auth_user_data;
@@ -417,27 +418,45 @@ e_cal_init (ECal *ecal)
* Called when the calendar server dies.
*/
static void
-gdbus_cal_destroyed_cb (gpointer data, GObject *object)
+gdbus_cal_closed_cb (GDBusConnection *connection, gboolean remote_peer_vanished, GError *error, ECal *ecal)
{
- ECal *ecal = data;
- ECalPrivate *priv;
+ GError *err = NULL;
- g_assert (E_IS_CAL (ecal));
+ g_assert (E_IS_CAL (ecal));
- priv = ecal->priv;
+ if (error) {
+ err = g_error_copy (error);
+ unwrap_gerror (&err);
+ }
- g_warning (G_STRLOC ": e-d-s proxy died");
+ if (err) {
+ g_debug (G_STRLOC ": ECal GDBus connection is closed%s: %s", remote_peer_vanished ? ", remote peer vanished" : "", err->message);
+ g_error_free (err);
+ } else {
+ g_debug (G_STRLOC ": ECal GDBus connection is closed%s", remote_peer_vanished ? ", remote peer vanished" : "");
+ }
- /* Ensure that everything relevant is reset */
- LOCK_FACTORY ();
- cal_factory_proxy = NULL;
- priv->gdbus_cal = NULL;
- priv->load_state = E_CAL_LOAD_NOT_LOADED;
- UNLOCK_FACTORY ();
+ /* Ensure that everything relevant is NULL */
+ LOCK_FACTORY ();
+
+ if (ecal->priv->gdbus_cal) {
+ g_object_unref (ecal->priv->gdbus_cal);
+ ecal->priv->gdbus_cal = NULL;
+ }
+
+ UNLOCK_FACTORY ();
g_signal_emit (G_OBJECT (ecal), e_cal_signals [BACKEND_DIED], 0);
}
+static void
+gdbus_cal_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_cal_closed_cb (connection, TRUE, NULL, user_data);
+}
+
/* Dispose handler for the calendar ecal */
static void
e_cal_dispose (GObject *object)
@@ -450,8 +469,11 @@ e_cal_dispose (GObject *object)
if (priv->gdbus_cal) {
GError *error = NULL;
+ GDBusConnection *connection = g_dbus_proxy_get_connection (G_DBUS_PROXY (priv->gdbus_cal));
- g_object_weak_unref (G_OBJECT (priv->gdbus_cal), gdbus_cal_destroyed_cb, ecal);
+ g_signal_handlers_disconnect_by_func (connection, gdbus_cal_closed_cb, ecal);
+ g_dbus_connection_signal_unsubscribe (connection, priv->gone_signal_id);
+ priv->gone_signal_id = 0;
e_gdbus_cal_call_close_sync (priv->gdbus_cal, NULL, &error);
g_object_unref (priv->gdbus_cal);
@@ -601,17 +623,45 @@ e_cal_class_init (ECalClass *klass)
}
static void
-cal_factory_proxy_destroyed_cb (gpointer user_data, GObject *what)
+cal_factory_proxy_closed_cb (GDBusConnection *connection, gboolean remote_peer_vanished, GError *error, gpointer user_data)
{
+ GError *err = NULL;
+
LOCK_FACTORY ();
- cal_factory_proxy = NULL;
+ if (cal_factory_proxy) {
+ g_object_unref (cal_factory_proxy);
+ cal_factory_proxy = NULL;
+ }
+
+ if (error) {
+ err = g_error_copy (error);
+ unwrap_gerror (&err);
+ }
+
+ if (err) {
+ g_debug ("GDBus connection is closed%s: %s", remote_peer_vanished ? ", remote peer vanished" : "", err->message);
+ g_error_free (err);
+ } else {
+ g_debug ("GDBus connection is closed%s", remote_peer_vanished ? ", remote peer vanished" : "");
+ }
+
UNLOCK_FACTORY ();
}
+static void
+cal_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)
+{
+ /* signal subscription takes care of correct parameters,
+ thus just do what is to be done here */
+ cal_factory_proxy_closed_cb (connection, TRUE, NULL, user_data);
+}
+
/* one-time start up for libecal */
static gboolean
e_cal_activate (GError **error)
{
+ GDBusConnection *connection;
+
LOCK_FACTORY ();
if (G_LIKELY (cal_factory_proxy)) {
UNLOCK_FACTORY ();
@@ -631,7 +681,18 @@ e_cal_activate (GError **error)
return FALSE;
}
- g_object_weak_ref (G_OBJECT (cal_factory_proxy), cal_factory_proxy_destroyed_cb, NULL);
+ connection = g_dbus_proxy_get_connection (G_DBUS_PROXY (cal_factory_proxy));
+ g_dbus_connection_set_exit_on_close (connection, FALSE);
+ g_dbus_connection_signal_subscribe (connection,
+ NULL, /* sender */
+ "org.freedesktop.DBus", /* interface */
+ "NameOwnerChanged", /* member */
+ "/org/freedesktop/DBus", /* object_path */
+ "org.gnome.evolution.dataserver.Calendar", /* arg0 */
+ G_DBUS_SIGNAL_FLAGS_NONE,
+ cal_factory_connection_gone_cb, NULL, NULL);
+
+ g_signal_connect (connection, "closed", G_CALLBACK (cal_factory_proxy_closed_cb), NULL);
UNLOCK_FACTORY ();
@@ -771,6 +832,7 @@ e_cal_new (ESource *source, ECalSourceType type)
ECalPrivate *priv;
gchar *path, *xml;
GError *error = NULL;
+ GDBusConnection *connection;
g_return_val_if_fail (source && E_IS_SOURCE (source), NULL);
g_return_val_if_fail (type < E_CAL_SOURCE_TYPE_LAST, NULL);
@@ -819,7 +881,17 @@ e_cal_new (ESource *source, ECalSourceType type)
return NULL;
}
- g_object_weak_ref (G_OBJECT (priv->gdbus_cal), gdbus_cal_destroyed_cb, ecal);
+ connection = g_dbus_proxy_get_connection (G_DBUS_PROXY (priv->gdbus_cal));
+ 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.Calendar", /* arg0 */
+ G_DBUS_SIGNAL_FLAGS_NONE,
+ gdbus_cal_connection_gone_cb, ecal, NULL);
+ g_signal_connect (connection, "closed", G_CALLBACK (gdbus_cal_closed_cb), ecal);
+
g_signal_connect (priv->gdbus_cal, "auth-required", G_CALLBACK (auth_required_cb), ecal);
g_signal_connect (priv->gdbus_cal, "backend-error", G_CALLBACK (backend_error_cb), ecal);
g_signal_connect (priv->gdbus_cal, "readonly", G_CALLBACK (readonly_cb), ecal);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]