diff --git a/addressbook/libebook/e-book-client.c b/addressbook/libebook/e-book-client.c
index b0baea5..5b3a4a4 100644
--- a/addressbook/libebook/e-book-client.c
+++ b/addressbook/libebook/e-book-client.c
@@ -509,6 +509,32 @@ book_client_close_cb (GObject *source_object,
 	}
 }
 
+typedef struct {
+	GMutex mutex;
+	GCond condition;
+	guint watcher_id;
+} UnwatchBarrier;
+
+static gboolean
+unwatch_name_in_dbus_thread_idle_cb (gpointer data)
+{
+	UnwatchBarrier *barrier = (UnwatchBarrier *)data;
+
+	g_bus_unwatch_name (barrier->watcher_id);
+
+	g_message ("remove watcher");
+
+	g_mutex_lock (&barrier->mutex);
+
+	g_message ("signal parent thread");
+
+	barrier->watcher_id = 0;
+	g_cond_signal (&barrier->condition);
+	g_mutex_unlock (&barrier->mutex);
+
+	return FALSE;
+}
+
 static void
 book_client_dispose (GObject *object)
 {
@@ -546,22 +572,61 @@ book_client_dispose (GObject *object)
 		priv->direct_book = NULL;
 	}
 
-	/* Chain up to parent's dispose() method. */
-	G_OBJECT_CLASS (e_book_client_parent_class)->dispose (object);
-}
+	/* The intention here, is to avoid a race where the D-Bus thread is starting
+	 * to run book_client_name_vanished_cb() while the client thread is finalizing.
+	 *
+	 * In this case removing the watcher id will have negative consequences, since
+	 * it will immediately free the GWeakRef that is associated to 'priv->name_watcher_id',
+	 * causing g_weak_ref_get() to access invalid memory (since the callback can be
+	 * triggering at exactly the same time).
+	 *
+	 * The following code attempts to synchronize the removal of 'priv->name_watcher_id'
+	 * in the D-Bus thread so that name_vanished_cb() is either called before removing
+	 * the watcher, or not called at all.
+	 */
+	if (priv->name_watcher_id) {
+		GMainContext *main_context;
+		GSource *idle_source;
+		UnwatchBarrier barrier;
 
-static void
-book_client_finalize (GObject *object)
-{
-	EBookClientPrivate *priv;
+		/* Initialize Barrier */
+		barrier.watcher_id = priv->name_watcher_id;
+		g_cond_init (&barrier.condition);
+		g_mutex_init (&barrier.mutex);
 
-	priv = E_BOOK_CLIENT_GET_PRIVATE (object);
+		/* Queue the idle in the thread context */
+		main_context = book_client_ref_dbus_main_context ();
+		idle_source = g_idle_source_new ();
+		g_source_set_callback (
+		        idle_source,
+			unwatch_name_in_dbus_thread_idle_cb,
+			&barrier, NULL);
+		g_source_attach (idle_source, main_context);
+		g_source_unref (idle_source);
+		g_main_context_unref (main_context);
 
-	if (priv->name_watcher_id > 0)
-		g_bus_unwatch_name (priv->name_watcher_id);
+		/* g_cond_wait() will allow the code in unwatch_name_in_dbus_thread_idle_cb() 
+		 * to run and signal us that watcher_id is set to 0, it's possible that
+		 * it already ran at this point
+		 */
+		g_mutex_lock (&barrier.mutex);
 
-	/* Chain up to parent's finalize() method. */
-	G_OBJECT_CLASS (e_book_client_parent_class)->finalize (object);
+		g_message ("Wait for watcher to be removed");
+
+		while (barrier.watcher_id > 0) {
+			g_cond_wait (&barrier.condition, &barrier.mutex);
+		}
+		g_mutex_unlock (&barrier.mutex);
+
+		/* Cleanup barrier */
+		g_cond_clear (&barrier.condition);
+		g_mutex_clear (&barrier.mutex);
+
+		priv->name_watcher_id = 0;
+	}
+
+	/* Chain up to parent's dispose() method. */
+	G_OBJECT_CLASS (e_book_client_parent_class)->dispose (object);
 }
 
 static GDBusProxy *
@@ -910,7 +975,6 @@ e_book_client_class_init (EBookClientClass *class)
 
 	object_class = G_OBJECT_CLASS (class);
 	object_class->dispose = book_client_dispose;
-	object_class->finalize = book_client_finalize;
 
 	client_class = E_CLIENT_CLASS (class);
 	client_class->get_dbus_proxy = book_client_get_dbus_proxy;
