Hello Marcel!

We have released SyncEvolution 1.0 alpha 1, based on a modified copy of
the gdbus source code. The patches include several bug fixes and some
extensions that we needed in SyncEvolution. Attached is the complete
patch series - better late than never, right? ;-}

One observation that we made on Moblin which might be of interest to you
and the obexd team: gdbus conflicts with dbus-glib, which is invoked
indirectly by the libecal/ebook in Moblin and (soon) Evolution 2.30. As
a workaround we are using a private libdbus connection in gdbus, because
that was easier than waiting for a fix in libecal/ebook (Moblin Bugzilla
#8460).

Regarding the name "gdbus": I have seen it also getting used for some
D-Bus support code that is going to be merged into glib. Now a Google
search mostly brings up hits for that other project.

Moving gdbus patches between upstream and SyncEvolution is automated
with some scripts in our "build" directory. I've done some trial runs,
but we'll have to see how this works out in practice, in particular when
you do not merge patches as they are.

Because this could be problematic, I haven't cleaned up the patches
despite some minor white space issues reported by "git am" and a partly
faulty vsprintf() commit (fixed in a later commit). Please let me know
how you want to handle this.

-- 
Best Regards, Patrick Ohly

The content of this message is my personal opinion only and although
I am an employee of Intel, the statements I make here in no way
represent Intel's position on the issue, nor am I authorized to speak
on behalf of Intel on this matter.

>From 14bbd3dd72114deaa96de16028b3822ecea8c40e Mon Sep 17 00:00:00 2001
From: Patrick Ohly <[email protected]>
Date: Wed, 26 Aug 2009 11:04:11 +0200
Subject: [PATCH 01/12] example.c: demonstrate segfault in watch handling

g_dbus_add_disconnect_watch/g_dbus_remove_watch/g_dbus_add_disconnect_watch segfaults:
=28457== Invalid read of size 4
==28457==    at 0x4E32238: g_dbus_add_service_watch (watch.c:239)
==28457==    by 0x4E3263C: g_dbus_add_disconnect_watch (watch.c:422)
==28457==    by 0x401007: main (example.c:108)
==28457==  Address 0x5ae5350 is 16 bytes inside a block of size 24 free'd
==28457==    at 0x4C265AF: free (vg_replace_malloc.c:323)
==28457==    by 0x4E32419: g_dbus_remove_watch (watch.c:312)
==28457==    by 0x400FE9: main (example.c:107)
---
 test/example.c |    5 +++++
 1 files changed, 5 insertions(+), 0 deletions(-)

diff --git a/test/example.c b/test/example.c
index 8a98219..74c3e38 100644
--- a/test/example.c
+++ b/test/example.c
@@ -75,6 +75,7 @@ int main(int argc, char *argv[])
 	DBusConnection *conn;
 	DBusError err;
 	struct sigaction sa;
+	guint watch;
 
 	memset(&sa, 0, sizeof(sa));
 	sa.sa_handler = sig_term;
@@ -102,6 +103,10 @@ int main(int argc, char *argv[])
 	g_dbus_register_interface(conn, "/test", "org.example.Test",
 					methods, signals, NULL, NULL, NULL);
 
+	watch = g_dbus_add_disconnect_watch(conn, "com.no.such.service", NULL, NULL, NULL);
+	g_dbus_remove_watch(conn, watch);
+	watch = g_dbus_add_disconnect_watch(conn, "com.still.no.such.service", NULL, NULL, NULL);
+
 	g_main_loop_run(main_loop);
 
 	g_dbus_unregister_interface(conn, "/test", "org.example.Test");
-- 
1.6.5

>From 3bb0e1e01230f50f66b3004ca385d73c49bff2c6 Mon Sep 17 00:00:00 2001
From: Patrick Ohly <[email protected]>
Date: Wed, 26 Aug 2009 11:05:14 +0200
Subject: [PATCH 02/12] fix for ConnectionData handling

g_dbus_remove_watch() decremented the slot ref count and freed
the ConnectionData associated with it if the ref count reached
zero. This left a dangling pointer to the ConnectionData instance
in the slot, which was found and used once the slot got recycled.

The new approach is to clear the data pointer in the slot if
its last user (watch or handler) is gone.
---
 src/watch.c |   13 +++++++------
 1 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/src/watch.c b/src/watch.c
index 74d1b6c..8147684 100644
--- a/src/watch.c
+++ b/src/watch.c
@@ -302,16 +302,17 @@ gboolean g_dbus_remove_watch(DBusConnection *connection, guint tag)
 	return FALSE;
 
 done:
-	dbus_connection_free_data_slot(&connection_slot);
-
-	DBG("connection slot %d", connection_slot);
-
-	if (connection_slot < 0) {
+        if (!data->watches && !data->handlers) {
 		dbus_connection_remove_filter(connection,
 						filter_function, data);
-		g_free(data);
+		dbus_connection_set_data(connection, connection_slot, NULL, NULL);
+                g_free(data);
 	}
 
+	dbus_connection_free_data_slot(&connection_slot);
+
+	DBG("connection slot %d", connection_slot);
+
 	return TRUE;
 }
 
-- 
1.6.5

>From d0084fd7b13b7f4665c223877f77576b08624dbf Mon Sep 17 00:00:00 2001
From: Patrick Ohly <[email protected]>
Date: Wed, 26 Aug 2009 11:24:52 +0200
Subject: [PATCH 03/12] watch: call dbus_bus_remove_match() for each dbus_bus_add_match()

Without the remove call the matches would accumulate over time,
which can't be good for the dbus-server.
---
 src/watch.c |   31 ++++++++++++++++++++++---------
 1 files changed, 22 insertions(+), 9 deletions(-)

diff --git a/src/watch.c b/src/watch.c
index 8147684..d10b567 100644
--- a/src/watch.c
+++ b/src/watch.c
@@ -40,6 +40,7 @@ typedef struct {
 	guint id;
 	char *name;
 	void *user_data;
+	char *match;
 	GDBusWatchFunction connect;
 	GDBusWatchFunction disconn;
 	GDBusDestroyFunction destroy;
@@ -55,6 +56,7 @@ typedef struct {
 typedef struct {
 	guint id;
 	void *user_data;
+	char *match;
 	GDBusSignalFunction function;
 	GDBusDestroyFunction destroy;
 } SignalData;
@@ -195,7 +197,6 @@ guint g_dbus_add_service_watch(DBusConnection *connection, const char *name,
 	ConnectionData *data;
 	WatchData *watch;
 	DBusError error;
-	gchar *match;
 
 	DBG("connection %p name %s", connection, name);
 
@@ -218,24 +219,20 @@ guint g_dbus_add_service_watch(DBusConnection *connection, const char *name,
 	watch->connect = connect;
 	watch->disconn = disconnect;
 	watch->destroy = destroy;
-
-	match = g_strdup_printf("interface=%s,member=NameOwnerChanged,arg0=%s",
+	watch->match = g_strdup_printf("interface=%s,member=NameOwnerChanged,arg0=%s",
 						DBUS_INTERFACE_DBUS, name);
-	if (match == NULL)
+	if (watch->match == NULL)
 		goto error;
 
 	dbus_error_init(&error);
 
-	dbus_bus_add_match(connection, match, &error);
+	dbus_bus_add_match(connection, watch->match, &error);
 
 	if (dbus_error_is_set(&error) == TRUE) {
 		dbus_error_free(&error);
-		g_free(match);
 		goto error;
 	}
 
-	g_free(match);
-
 	watch->id = data->next_id++;
 
 	data->watches = g_slist_append(data->watches, watch);
@@ -245,8 +242,10 @@ guint g_dbus_add_service_watch(DBusConnection *connection, const char *name,
 	return watch->id;
 
 error:
-	if (watch != NULL)
+	if (watch != NULL) {
 		g_free(watch->name);
+		g_free(watch->match);
+	}
 	g_free(watch);
 
 	put_connection_data(connection);
@@ -281,7 +280,9 @@ gboolean g_dbus_remove_watch(DBusConnection *connection, guint tag)
 			data->watches = g_slist_remove(data->watches, watch);
 			if (watch->destroy != NULL)
 				watch->destroy(watch->user_data);
+			dbus_bus_remove_match(connection, watch->match, NULL);
 			g_free(watch->name);
+                        g_free(watch->match);
 			g_free(watch);
 			goto done;
 		}
@@ -294,6 +295,8 @@ gboolean g_dbus_remove_watch(DBusConnection *connection, guint tag)
 			data->handlers = g_slist_remove(data->handlers, signal);
 			if (signal->destroy != NULL)
 				signal->destroy(signal->user_data);
+			dbus_bus_remove_match(connection, signal->match, NULL);
+			g_free(signal->match);
 			g_free(signal);
 			goto done;
 		}
@@ -345,6 +348,8 @@ void g_dbus_remove_all_watches(DBusConnection *connection)
 
 		if (watch->destroy != NULL)
 			watch->destroy(watch->user_data);
+		dbus_bus_remove_match(connection, watch->match, NULL);
+		g_free(watch->match);
 		g_free(watch->name);
 		g_free(watch);
 
@@ -362,6 +367,8 @@ void g_dbus_remove_all_watches(DBusConnection *connection)
 
 		if (signal->destroy != NULL)
 			signal->destroy(signal->user_data);
+		dbus_bus_remove_match(connection, signal->match, NULL);
+		g_free(signal->match);
 		g_free(signal);
 
 		dbus_connection_free_data_slot(&connection_slot);
@@ -467,6 +474,10 @@ guint g_dbus_add_signal_watch(DBusConnection *connection,
 	if (signal == NULL)
 		goto error;
 
+	signal->match = g_strdup(rule);
+	if (!signal->match)
+		goto error;
+
 	signal->user_data = user_data;
 
 	signal->function = function;
@@ -490,6 +501,8 @@ guint g_dbus_add_signal_watch(DBusConnection *connection,
 	return signal->id;
 
 error:
+        if (signal)
+		g_free(signal->match);
 	g_free(signal);
 
 	put_connection_data(connection);
-- 
1.6.5

>From 170702da7161a28241a3e271a338892b2efb41a2 Mon Sep 17 00:00:00 2001
From: Patrick Ohly <[email protected]>
Date: Thu, 20 Aug 2009 19:17:16 +0200
Subject: [PATCH 04/12] g_dbus_create_error(): implemented support for detailed error description

The API had printf-style formatting for a detailed error description,
but that information was ignored. Added a sprintf variant which
allocates the resulting string dynamically, based on vsnprintf().
---
 src/object.c |   43 ++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 42 insertions(+), 1 deletions(-)

diff --git a/src/object.c b/src/object.c
index 2f828e0..b390ebb 100644
--- a/src/object.c
+++ b/src/object.c
@@ -25,6 +25,8 @@
 
 #include <stdarg.h>
 #include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
 
 #include <dbus/dbus.h>
 
@@ -1002,6 +1004,39 @@ gboolean g_dbus_unregister_interface(DBusConnection *connection,
 	return TRUE;
 }
 
+char *printf_dyn(const char *format, va_list ap)
+{
+    va_list aq;
+
+    char *buffer = NULL;
+    ssize_t size = 0;
+    ssize_t realsize = 255;
+    do {
+        // vsnprintf() destroys ap, so make a copy first
+        va_copy(aq, ap);
+
+        if (size < realsize) {
+            buffer = (char *)realloc(buffer, realsize + 1);
+            if (!buffer) {
+                if (buffer) {
+                    free(buffer);
+                }
+                return "";
+            }
+            size = realsize;
+        }
+
+        realsize = vsnprintf(buffer, size + 1, format, aq);
+        if (realsize == -1) {
+            // old-style vnsprintf: exact len unknown, try again with doubled size
+            realsize = size * 2;
+        }
+        va_end(aq);
+    } while(realsize > size);
+
+    return buffer;
+}
+
 /**
  * g_dbus_create_error_valist:
  * @message: the originating message
@@ -1016,9 +1051,15 @@ gboolean g_dbus_unregister_interface(DBusConnection *connection,
 DBusMessage *g_dbus_create_error_valist(DBusMessage *message, const char *name,
 						const char *format, va_list args)
 {
+	DBusMessage *msg;
+        char *descr;
+
 	DBG("message %p name %s", message, name);
 
-	return dbus_message_new_error(message, name, NULL);
+	descr = printf_dyn(format, args);
+	msg = dbus_message_new_error(message, name, descr);
+	free(descr);
+	return msg;
 }
 
 /**
-- 
1.6.5

>From f113260eb33bbefc82f51ce1c0a93cd14c683ae5 Mon Sep 17 00:00:00 2001
From: Patrick Ohly <[email protected]>
Date: Thu, 27 Aug 2009 14:07:36 +0200
Subject: [PATCH 05/12] g_dbus_unregister_object(): fix same invalid memory reuse as for watches

g_dbus_unregister_object() has the same logical flaw as g_dbus_remove_watch():
it left a dangling pointer to its data in the connection slot. This pointer
was found when the slot was reused in the following call sequence:
g_dbus_register_interface()
g_dbus_unregister_interface()
g_dbus_register_interface()

The result was a segfault.
---
 src/object.c |    4 +++-
 1 files changed, 3 insertions(+), 1 deletions(-)

diff --git a/src/object.c b/src/object.c
index b390ebb..0284995 100644
--- a/src/object.c
+++ b/src/object.c
@@ -759,6 +759,8 @@ static gboolean g_dbus_unregister_object(DBusConnection *connection,
 	g_static_mutex_lock(&data->mutex);
 
 	data->objects = g_slist_remove(data->objects, object);
+        if (!data->objects)
+		dbus_connection_set_data(connection, connection_slot, NULL, NULL);
 
 	g_static_mutex_unlock(&data->mutex);
 
@@ -766,7 +768,7 @@ static gboolean g_dbus_unregister_object(DBusConnection *connection,
 
 	DBG("connection slot %d", connection_slot);
 
-	if (connection_slot < 0) {
+	if (!data->objects) {
 		g_static_mutex_free(&data->mutex);
 		g_free(data);
 	}
-- 
1.6.5

>From 5149662f0935be99e470d10ed16e9bf19f090772 Mon Sep 17 00:00:00 2001
From: Patrick Ohly <[email protected]>
Date: Thu, 27 Aug 2009 15:20:24 +0200
Subject: [PATCH 06/12] gdbus: allow registering multiple interfaces per object

Apparently this was part of the design (there was a refcount
in ObjectData and a list of interfaces), but the implementation
didn't really use much of that.

Added a check whether there is already an object registered under
a path and reuse that object when adding further interfaces. Only
remove the object when its last interface is gone.
---
 src/object.c |   69 +++++++++++++++++++++++++++++++++++++---------------------
 1 files changed, 44 insertions(+), 25 deletions(-)

diff --git a/src/object.c b/src/object.c
index 0284995..448fef7 100644
--- a/src/object.c
+++ b/src/object.c
@@ -71,6 +71,20 @@ static InterfaceData *find_interface(GSList *interfaces, const char *name)
 	return NULL;
 }
 
+static ObjectData *find_object(GSList *objects, const char *path)
+{
+	GSList *list;
+
+	for (list = objects; list; list = list->next) {
+		ObjectData *object = list->data;
+
+		if (strcmp(path, object->path) == 0)
+			return object;
+	}
+
+	return NULL;
+}
+
 static GDBusPropertyTable *find_property(InterfaceData *interface,
 					 		const char *name)
 {
@@ -697,31 +711,33 @@ static gboolean g_dbus_register_object(DBusConnection *connection,
 
 	DBG("connection data %p", data);
 
-	object = g_new0(ObjectData, 1);
+	g_static_mutex_lock(&data->mutex);
 
-	object->refcount = 1;
+	object = find_object(data->objects, path);
+
+	if (!object) {
+		object = g_new0(ObjectData, 1);
+		g_static_mutex_init(&object->mutex);
+		object->path = g_strdup(path);
+		object->interfaces = NULL;
+		object->refcount = 0;
+		object->introspect = generate_introspect(connection, path, object);
+		if (dbus_connection_register_object_path(connection, path,
+						&object_table, object) == FALSE) {
+			g_free(object->introspect);
+			g_free(object);
+			return FALSE;
+		}
 
-	g_static_mutex_init(&object->mutex);
+		data->objects = g_slist_append(data->objects, object);
+        }
 
-	object->path = g_strdup(path);
-	object->interfaces = NULL;
-	object->introspect = generate_introspect(connection, path, object);
+	object->refcount++;
 
-	if (dbus_connection_register_object_path(connection, path,
-					&object_table, object) == FALSE) {
-		g_free(object->introspect);
-		g_free(object);
-		return FALSE;
-	}
+	g_static_mutex_unlock(&data->mutex);
 
 	DBG("object data %p", object);
 
-	g_static_mutex_lock(&data->mutex);
-
-	data->objects = g_slist_append(data->objects, object);
-
-	g_static_mutex_unlock(&data->mutex);
-
 	update_parent(connection, path);
 
 	return TRUE;
@@ -742,6 +758,8 @@ static gboolean g_dbus_unregister_object(DBusConnection *connection,
 {
 	ConnectionData *data;
 	ObjectData *object;
+	gboolean result = TRUE;
+
 
 	DBG("connection %p path %s", connection, path);
 
@@ -758,9 +776,13 @@ static gboolean g_dbus_unregister_object(DBusConnection *connection,
 
 	g_static_mutex_lock(&data->mutex);
 
-	data->objects = g_slist_remove(data->objects, object);
-        if (!data->objects)
-		dbus_connection_set_data(connection, connection_slot, NULL, NULL);
+	object->refcount--;
+	if (!object->refcount) {
+		result = dbus_connection_unregister_object_path(connection, path);
+		data->objects = g_slist_remove(data->objects, object);
+        	if (!data->objects)
+			dbus_connection_set_data(connection, connection_slot, NULL, NULL);
+        }
 
 	g_static_mutex_unlock(&data->mutex);
 
@@ -773,12 +795,9 @@ static gboolean g_dbus_unregister_object(DBusConnection *connection,
 		g_free(data);
 	}
 
-	if (dbus_connection_unregister_object_path(connection, path) == FALSE)
-		return FALSE;
-
 	update_parent(connection, path);
 
-	return TRUE;
+	return result;
 }
 
 #if 0
-- 
1.6.5

>From ed8b98aa0c72431c3500193d1ba82ff3156974a9 Mon Sep 17 00:00:00 2001
From: Patrick Ohly <[email protected]>
Date: Wed, 2 Sep 2009 17:18:03 +0200
Subject: [PATCH 07/12] gdbus: fixed segfault in watch disconnect function

If the apps callback function removes the watch that
triggered it, then disconnect_function() used a dangling
data pointer to retrieve the id (first problem) and
g_dbus_remove_watch() used a -1 connection_slot (second
problem, only occurs when the current watch was the
last one).

Fixed by storing the ID in a temporary variable and
adding a connection_slot check to g_dbus_remove_watch(),
similar to the one which was already in g_dbus_remove_all_watches().
---
 src/watch.c |   10 +++++++++-
 1 files changed, 9 insertions(+), 1 deletions(-)

diff --git a/src/watch.c b/src/watch.c
index d10b567..3e9081c 100644
--- a/src/watch.c
+++ b/src/watch.c
@@ -269,6 +269,9 @@ gboolean g_dbus_remove_watch(DBusConnection *connection, guint tag)
 
 	DBG("connection %p tag %d", connection, tag);
 
+	if (connection_slot < 0)
+		return FALSE;
+
 	data = dbus_connection_get_data(connection, connection_slot);
 	if (data == NULL)
 		return FALSE;
@@ -387,9 +390,14 @@ static void disconnect_function(DBusConnection *connection, void *user_data)
 {
 	DisconnectData *data = user_data;
 
+	// The callback function might remove the watch,
+	// which invalidates the data pointer. Remember
+	// the ID.
+	guint id = data->id;
+
 	data->function(connection, data->user_data);
 
-	g_dbus_remove_watch(connection, data->id);
+	g_dbus_remove_watch(connection, id);
 }
 
 static void disconnect_release(void *user_data)
-- 
1.6.5

>From f4acde1fbf18ec11a9c81b468247905f37c4d5a2 Mon Sep 17 00:00:00 2001
From: Patrick Ohly <[email protected]>
Date: Mon, 12 Oct 2009 20:48:25 +0200
Subject: [PATCH 08/12] gdbus: add _NONE = 0 enum value for C++

In C++, 0 is not automatically casted into an enum. This patch
adds enum names for the empty bit field, which makes C++ code
using gdbus a bit easier to read.
---
 src/gdbus.h |    3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)

diff --git a/src/gdbus.h b/src/gdbus.h
index 575e1f3..b1797a0 100644
--- a/src/gdbus.h
+++ b/src/gdbus.h
@@ -116,6 +116,7 @@ typedef dbus_bool_t (* GDBusPropertySetFunction) (DBusConnection *connection,
  * Method flags
  */
 typedef enum {
+	G_DBUS_METHOD_FLAG_NONE = 0,
 	G_DBUS_METHOD_FLAG_DEPRECATED = (1 << 0),
 	G_DBUS_METHOD_FLAG_NOREPLY    = (1 << 1),
 	G_DBUS_METHOD_FLAG_ASYNC      = (1 << 2),
@@ -128,6 +129,7 @@ typedef enum {
  * Signal flags
  */
 typedef enum {
+	G_DBUS_SIGNAL_FLAG_NONE = 0,
 	G_DBUS_SIGNAL_FLAG_DEPRECATED = (1 << 0),
 } GDBusSignalFlags;
 
@@ -138,6 +140,7 @@ typedef enum {
  * Property flags
  */
 typedef enum {
+	G_DBUS_PROPERTY_FLAG_NONE = 0,
 	G_DBUS_PROPERTY_FLAG_DEPRECATED = (1 << 0),
 } GDBusPropertyFlags;
 
-- 
1.6.5

>From e95a3e6cc5c8716aae84ff40439000fcf733b6e2 Mon Sep 17 00:00:00 2001
From: Patrick Ohly <[email protected]>
Date: Mon, 12 Oct 2009 20:51:28 +0200
Subject: [PATCH 09/12] gdbus: per-method callback data

The traditional usage of method callbacks is that all callbacks
share the same global data pointer. When composing a D-Bus object
from several independent modules this may be too limited, for
example when using C++.

This patch introduces G_DBUS_METHOD_FLAG_METHOD_DATA and new
fields at the end of GDBusMethodTable. Old code works as before.
New code which sets the flag is passed the new "method_data"
value as its "user_data" pointer.

This implies that the GDBusMethodTable has to be built up dynamically.
It is still owned and managed by the caller of libgdbus. To
simplify this, a new "destroy" callback can be stored inside the
GDBusMethodTable.
---
 src/gdbus.h  |   12 ++++++++++++
 src/object.c |    6 +++++-
 2 files changed, 17 insertions(+), 1 deletions(-)

diff --git a/src/gdbus.h b/src/gdbus.h
index b1797a0..8149637 100644
--- a/src/gdbus.h
+++ b/src/gdbus.h
@@ -112,6 +112,10 @@ typedef dbus_bool_t (* GDBusPropertySetFunction) (DBusConnection *connection,
  * @G_DBUS_METHOD_FLAG_DEPRECATED: annotate deprecated methods
  * @G_DBUS_METHOD_FLAG_NOREPLY: annotate methods with no reply
  * @G_DBUS_METHOD_FLAG_ASYNC: annotate asynchronous methods
+ * @G_DBUS_METHOD_FLAG_METHOD_DATA: the method is passed the
+ *                                  GDBusMethodTable method_data pointer
+ *                                  instead of the g_dbus_register_interface()
+ *                                  user_data pointer
  *
  * Method flags
  */
@@ -120,6 +124,7 @@ typedef enum {
 	G_DBUS_METHOD_FLAG_DEPRECATED = (1 << 0),
 	G_DBUS_METHOD_FLAG_NOREPLY    = (1 << 1),
 	G_DBUS_METHOD_FLAG_ASYNC      = (1 << 2),
+	G_DBUS_METHOD_FLAG_METHOD_DATA = (1 << 3),
 } GDBusMethodFlags;
 
 /**
@@ -151,6 +156,11 @@ typedef enum {
  * @reply: reply signature
  * @function: method function
  * @flags: method flags
+ * @method_data: passed as GDBusMethodFunction user_data if
+ *               G_DBUS_METHOD_FLAG_METHOD_DATA is set
+ * @destroy: destructor function for method table; not called
+ *           by gdbus itself, because it never frees GDBusMethodTable
+ *           entries, but useful in upper layers
  *
  * Method table
  */
@@ -160,6 +170,8 @@ typedef struct {
 	const char *reply;
 	GDBusMethodFunction function;
 	GDBusMethodFlags flags;
+	void *method_data;
+	GDBusDestroyFunction destroy;
 } GDBusMethodTable;
 
 /**
diff --git a/src/object.c b/src/object.c
index 448fef7..f35ac31 100644
--- a/src/object.c
+++ b/src/object.c
@@ -615,7 +615,11 @@ static DBusHandlerResult handle_message(DBusConnection *connection,
 			continue;
 
 		reply = method->function(connection,
-						message, interface->user_data);
+						message,
+						(method->flags & 
+						 G_DBUS_METHOD_FLAG_METHOD_DATA) ?
+						method->method_data :
+						interface->user_data);
 
 		if (method->flags & G_DBUS_METHOD_FLAG_NOREPLY) {
 			if (reply != NULL)
-- 
1.6.5

>From 870ebe37a52e98eae93fc190d71c68c35317017c Mon Sep 17 00:00:00 2001
From: Chen Congwu <[email protected]>
Date: Tue, 10 Nov 2009 13:52:42 +0800
Subject: [PATCH 10/12] gdbus: fix a compile error

Need to include stdint for uint
---
 src/gdbus.h |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/src/gdbus.h b/src/gdbus.h
index 8149637..8a7e349 100644
--- a/src/gdbus.h
+++ b/src/gdbus.h
@@ -27,6 +27,7 @@ extern "C" {
 #endif
 
 #include <stdarg.h>
+#include <stdint.h>
 
 #include <dbus/dbus.h>
 #include <glib.h>
-- 
1.6.5

>From 7781140183eeacba26c79c24cb4d377f698b41bf Mon Sep 17 00:00:00 2001
From: Patrick Ohly <[email protected]>
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

>From 984654716ae602c053c00600509bb40bf20bea1d Mon Sep 17 00:00:00 2001
From: Patrick Ohly <[email protected]>
Date: Wed, 9 Dec 2009 12:19:44 +0100
Subject: [PATCH 12/12] gdbus: fixed g_dbus_create_error_valist() error handling

Out-of-memory errors were not handled correctly:
- The code using realloc() might have leaked a string.
- A static pointer was used to avoid further memory
  allocation errors, but the caller then would have
  freed it => try strdup() and check result in caller
  instead.
---
 src/object.c |   15 +++++++++------
 1 files changed, 9 insertions(+), 6 deletions(-)

diff --git a/src/object.c b/src/object.c
index f35ac31..8004a78 100644
--- a/src/object.c
+++ b/src/object.c
@@ -1041,12 +1041,13 @@ char *printf_dyn(const char *format, va_list ap)
         va_copy(aq, ap);
 
         if (size < realsize) {
+            char *oldbuffer = buffer;
             buffer = (char *)realloc(buffer, realsize + 1);
             if (!buffer) {
-                if (buffer) {
-                    free(buffer);
+                if (oldbuffer) {
+                    free(oldbuffer);
                 }
-                return "";
+                return strdup("");
             }
             size = realsize;
         }
@@ -1076,14 +1077,16 @@ char *printf_dyn(const char *format, va_list ap)
 DBusMessage *g_dbus_create_error_valist(DBusMessage *message, const char *name,
 						const char *format, va_list args)
 {
-	DBusMessage *msg;
+	DBusMessage *msg = NULL;
         char *descr;
 
 	DBG("message %p name %s", message, name);
 
 	descr = printf_dyn(format, args);
-	msg = dbus_message_new_error(message, name, descr);
-	free(descr);
+        if (descr) {
+            msg = dbus_message_new_error(message, name, descr);
+            free(descr);
+        }
 	return msg;
 }
 
-- 
1.6.5

_______________________________________________
SyncEvolution mailing list
[email protected]
http://lists.syncevolution.org/listinfo/syncevolution

Reply via email to