>From 7781140183eeacba26c79c24cb4d377f698b41bf Mon Sep 17 00:00:00 2001
From: Patrick Ohly <patrick.ohly@intel.com>
Date: Fri, 4 Dec 2009 12:47:47 +0100
Subject: [PATCH 11/12] gdbus: allow using private connection

This change was necessary because it turned out that using
g_dbus_setup_bus() and later dbus_g_bus_get() leads to problems
(assertion about watch data on Moblin 2.1, CRITICAL warning
and possibly other issues on Debian Lenny).

It seems that sharing a DBusConnection between different layers on top
of libdbus is either not supported or incorrectly implemented, at
least in glib-dbus.

The problem was found in SyncEvolution when using a libecal/ebook
which call D-Bus under the hood (Moblin Bugzilla #8460). SyncEvolution
has no control over those calls, therefore making the connection used
by the syncevo-dbus-server private was the easier alternative.
---
 src/gdbus.h    |    2 ++
 src/mainloop.c |   20 ++++++++++++++++----
 2 files changed, 18 insertions(+), 4 deletions(-)

diff --git a/src/gdbus.h b/src/gdbus.h
index 8a7e349..e10dcae 100644
--- a/src/gdbus.h
+++ b/src/gdbus.h
@@ -208,10 +208,12 @@ typedef struct {
 } GDBusPropertyTable;
 
 void g_dbus_setup_connection(DBusConnection *connection,
+						gboolean unshared,
 						GMainContext *context);
 void g_dbus_cleanup_connection(DBusConnection *connection);
 
 DBusConnection *g_dbus_setup_bus(DBusBusType type, const char *name,
+							gboolean unshared,
 							DBusError *error);
 
 DBusConnection *g_dbus_setup_address(const char *address, DBusError *error);
diff --git a/src/mainloop.c b/src/mainloop.c
index fd7a71b..1e5113e 100644
--- a/src/mainloop.c
+++ b/src/mainloop.c
@@ -39,6 +39,7 @@ typedef struct {
 	DBusConnection *connection;
 	GMainContext *context;
 	GSource *queue;
+	gboolean unshared;
 } ConnectionData;
 
 typedef struct {
@@ -317,6 +318,7 @@ static void wakeup_context(void *user_data)
 }
 
 static ConnectionData *setup_connection(DBusConnection *connection,
+						gboolean unshared,
 						GMainContext *context)
 {
 	ConnectionData *data;
@@ -326,6 +328,7 @@ static ConnectionData *setup_connection(DBusConnection *connection,
 	data = g_new0(ConnectionData, 1);
 
 	data->context = g_main_context_ref(context);
+	data->unshared = unshared;
 
 	DBG("connection data %p", data);
 
@@ -353,6 +356,8 @@ static void free_connection(void *memory)
 
 	//g_dbus_unregister_all_objects(data->connection);
 
+	if (data->unshared)
+		dbus_connection_close(data->connection);
 	dbus_connection_unref(data->connection);
 
 	g_main_context_unref(data->context);
@@ -363,6 +368,7 @@ static void free_connection(void *memory)
 /**
  * g_dbus_setup_connection:
  * @connection: a #DBusConnection
+ * @unshared: the connection is private and must be closed explicitly
  * @context: a #GMainContext or #NULL for default context
  *
  * Setup connection with main context
@@ -373,6 +379,7 @@ static void free_connection(void *memory)
  * doing something specialized.
  */
 void g_dbus_setup_connection(DBusConnection *connection,
+						gboolean unshared,
 						GMainContext *context)
 {
 	ConnectionData *data;
@@ -393,7 +400,7 @@ void g_dbus_setup_connection(DBusConnection *connection,
 	if (context == NULL)
 		context = g_main_context_default();
 
-	data = setup_connection(connection, context);
+	data = setup_connection(connection, unshared, context);
 	if (data == NULL)
 		return;
 
@@ -438,6 +445,9 @@ void g_dbus_cleanup_connection(DBusConnection *connection)
  * g_dbus_setup_bus:
  * @type: a #DBusBusType
  * @name: well known name
+ * @unshared: use dbus_bus_get_private() to ensure that we have the connection
+ *            for ourself (otherwise assertions and CRITICAL warnings were triggered
+ *            inside glib-dbus when the app also used that)
  * @error: a #DBusError
  *
  * Connect to bus and setup connection
@@ -449,13 +459,15 @@ void g_dbus_cleanup_connection(DBusConnection *connection)
  * Returns: newly setup #DBusConnection
  */
 DBusConnection *g_dbus_setup_bus(DBusBusType type, const char *name,
+							gboolean unshared,
 							DBusError *error)
 {
 	DBusConnection *connection;
 
 	DBG("type %d name %s error %p", type, name, error);
 
-	connection = dbus_bus_get(type, error);
+	connection = unshared ? dbus_bus_get_private(type, error) :
+		dbus_bus_get(type, error);
 
 	if (error != NULL) {
 		if (dbus_error_is_set(error) == TRUE)
@@ -481,7 +493,7 @@ DBusConnection *g_dbus_setup_bus(DBusBusType type, const char *name,
 		}
 	}
 
-	g_dbus_setup_connection(connection, NULL);
+	g_dbus_setup_connection(connection, unshared, NULL);
 
 	return connection;
 }
@@ -515,7 +527,7 @@ DBusConnection *g_dbus_setup_address(const char *address, DBusError *error)
 	if (connection == NULL)
 		return NULL;
 
-	g_dbus_setup_connection(connection, NULL);
+	g_dbus_setup_connection(connection, FALSE, NULL);
 
 	return connection;
 }
-- 
1.6.5

