1
diff --git a/dbus/dbus-gobject.c b/dbus/dbus-gobject.c
2
index f0c4df8..816194c 100644
3
--- a/dbus/dbus-gobject.c
4
+++ b/dbus/dbus-gobject.c
5
@@ -407,9 +407,18 @@ object_registration_free (ObjectRegistration *o)
9
+ GSList *registrations;
11
+ /* Ok, the object is still around; clear out this particular registration
12
+ * from the registrations list.
14
+ registrations = g_object_steal_data (o->object, "dbus_glib_object_registrations");
15
+ registrations = g_slist_remove (registrations, o);
17
+ if (registrations != NULL)
18
+ g_object_set_data (o->object, "dbus_glib_object_registrations", registrations);
20
g_object_weak_unref (o->object, object_registration_object_died, o);
21
- g_object_steal_data (o->object, "dbus_glib_object_registration");
25
g_free (o->object_path);
26
@@ -1741,30 +1750,19 @@ dbus_g_signal_closure_finalize (gpointer data,
30
-signal_emitter_marshaller (GClosure *closure,
32
- guint n_param_values,
33
- const GValue *param_values,
34
- gpointer invocation_hint,
35
- gpointer marshal_data)
36
+emit_signal_for_registration (ObjectRegistration *o,
37
+ DBusGSignalClosure *sigclosure,
39
+ guint n_param_values,
40
+ const GValue *param_values)
42
- DBusGSignalClosure *sigclosure;
48
- sigclosure = (DBusGSignalClosure *) closure;
50
- g_assert (retval == NULL);
52
- path = _dbus_gobject_get_path (sigclosure->object);
54
- g_assert (path != NULL);
56
- signal = dbus_message_new_signal (path,
57
- sigclosure->sigiface,
58
- sigclosure->signame);
59
+ signal = dbus_message_new_signal (o->object_path,
60
+ sigclosure->sigiface,
61
+ sigclosure->signame);
64
g_error ("out of memory");
65
@@ -1777,20 +1775,45 @@ signal_emitter_marshaller (GClosure *closure,
66
for (i = 1; i < n_param_values; i++)
68
if (!_dbus_gvalue_marshal (&iter,
69
- (GValue *) (&(param_values[i]))))
71
- g_warning ("failed to marshal parameter %d for signal %s",
72
- i, sigclosure->signame);
75
+ (GValue *) (&(param_values[i]))))
77
+ g_warning ("failed to marshal parameter %d for signal %s",
78
+ i, sigclosure->signame);
82
dbus_connection_send (DBUS_CONNECTION_FROM_G_CONNECTION (sigclosure->connection),
87
dbus_message_unref (signal);
91
+signal_emitter_marshaller (GClosure *closure,
93
+ guint n_param_values,
94
+ const GValue *param_values,
95
+ gpointer invocation_hint,
96
+ gpointer marshal_data)
98
+ DBusGSignalClosure *sigclosure;
99
+ GSList *registrations, *iter;
101
+ sigclosure = (DBusGSignalClosure *) closure;
103
+ g_assert (retval == NULL);
105
+ registrations = g_object_get_data (sigclosure->object, "dbus_glib_object_registrations");
107
+ for (iter = registrations; iter; iter = iter->next)
109
+ ObjectRegistration *o = iter->data;
111
+ emit_signal_for_registration (o, sigclosure, retval, n_param_values, param_values);
116
export_signals (DBusGConnection *connection, const GList *info_list, GObject *object)
119
@@ -2092,14 +2115,24 @@ void
120
dbus_g_connection_unregister_g_object (DBusGConnection *connection,
123
- ObjectRegistration *o;
124
+ GList *registrations, *iter;
126
+ /* Copy the list before iterating it: it will be modified in
127
+ * object_registration_free() each time an object path is unregistered.
129
+ registrations = g_list_copy (g_object_get_data (object, "dbus_glib_object_registrations"));
131
- o = g_object_get_data (object, "dbus_glib_object_registration");
132
+ g_return_if_fail (registrations != NULL);
134
- g_return_if_fail (o != NULL);
135
+ for (iter = registrations; iter; iter = iter->next)
137
+ ObjectRegistration *o = iter->data;
138
+ dbus_connection_unregister_object_path (DBUS_CONNECTION_FROM_G_CONNECTION (o->connection),
142
- dbus_connection_unregister_object_path (DBUS_CONNECTION_FROM_G_CONNECTION (o->connection),
144
+ g_list_free (registrations);
145
+ g_assert (g_object_get_data (object, "dbus_glib_object_registrations") == NULL);
149
@@ -2116,6 +2149,9 @@ dbus_g_connection_unregister_g_object (DBusGConnection *connection,
150
* The registration will be cancelled if either the #DBusConnection or
151
* the #GObject gets finalized, or if dbus_g_connection_unregister_g_object()
154
+ * Note: If an object is registered multiple times, the first registration
155
+ * takes priority for cases such as turning an object into an object path.
158
dbus_g_connection_register_g_object (DBusGConnection *connection,
159
@@ -2123,28 +2159,44 @@ dbus_g_connection_register_g_object (DBusGConnection *connection,
163
+ GSList *registrations, *iter;
164
ObjectRegistration *o;
165
+ gboolean is_first_registration;
167
g_return_if_fail (connection != NULL);
168
g_return_if_fail (at_path != NULL);
169
g_return_if_fail (G_IS_OBJECT (object));
171
- info_list = lookup_object_info (object);
172
- if (info_list == NULL)
173
+ /* This is a GSList of ObjectRegistration* */
174
+ registrations = g_object_steal_data (object, "dbus_glib_object_registrations");
176
+ for (iter = registrations; iter; iter = iter->next)
178
- g_warning ("No introspection data registered for object class \"%s\"",
179
- g_type_name (G_TYPE_FROM_INSTANCE (object)));
183
+ /* Silently ignore duplicate registrations */
184
+ if (strcmp (o->object_path, at_path) == 0)
188
- o = g_object_get_data (object, "dbus_glib_object_registration");
189
+ is_first_registration = registrations == NULL;
192
+ /* This is used to hook up signals below, but we do this check
193
+ * before trying to register the object to make sure we have
194
+ * introspection data for it.
196
+ if (is_first_registration)
198
- g_warning ("Object already registered at %s, can't re-register at %s",
199
- o->object_path, at_path);
201
+ info_list = lookup_object_info (object);
202
+ if (info_list == NULL)
204
+ g_warning ("No introspection data registered for object class \"%s\"",
205
+ g_type_name (G_TYPE_FROM_INSTANCE (object)));
212
o = object_registration_new (connection, at_path, object);
214
@@ -2155,12 +2207,22 @@ dbus_g_connection_register_g_object (DBusGConnection *connection,
216
g_error ("Failed to register GObject with DBusConnection");
217
object_registration_free (o);
218
+ g_list_free (info_list);
222
- export_signals (connection, info_list, object);
223
- g_list_free (info_list);
224
- g_object_set_data (object, "dbus_glib_object_registration", o);
225
+ if (is_first_registration)
227
+ /* This adds a hook into every signal for the object. Only do this
228
+ * on the first registration, because inside the signal marshaller
229
+ * we emit a signal for each registration.
231
+ export_signals (connection, info_list, object);
232
+ g_list_free (info_list);
235
+ registrations = g_slist_append (registrations, o);
236
+ g_object_set_data (object, "dbus_glib_object_registrations", registrations);
240
@@ -2539,15 +2601,20 @@ dbus_g_method_return_error (DBusGMethodInvocation *context, const GError *error)
244
-const char * _dbus_gobject_get_path (GObject *obj)
246
+_dbus_gobject_get_path (GObject *obj)
248
+ GSList *registrations;
249
ObjectRegistration *o;
251
- o = g_object_get_data (obj, "dbus_glib_object_registration");
252
+ registrations = g_object_get_data (obj, "dbus_glib_object_registrations");
255
+ if (registrations == NULL)
258
+ /* First one to have been registered wins */
259
+ o = registrations->data;
261
return o->object_path;
264
diff --git a/test/core/test-dbus-glib.c b/test/core/test-dbus-glib.c
265
index c6071a7..288606f 100644
266
--- a/test/core/test-dbus-glib.c
267
+++ b/test/core/test-dbus-glib.c
268
@@ -15,6 +15,7 @@ static const char *await_terminating_service = NULL;
269
static int n_times_foo_received = 0;
270
static int n_times_frobnicate_received = 0;
271
static int n_times_frobnicate_received_2 = 0;
272
+static int n_times_compat_frobnicate_received = 0;
273
static int n_times_sig0_received = 0;
274
static int n_times_sig1_received = 0;
275
static int n_times_sig2_received = 0;
276
@@ -139,6 +140,20 @@ frobnicate_signal_handler_2 (DBusGProxy *proxy,
280
+frobnicate_signal_handler_compat (DBusGProxy *proxy,
284
+ n_times_compat_frobnicate_received += 1;
286
+ g_assert (val == 42);
287
+ g_print ("Got Frobnicate signal (compat)\n");
289
+ g_main_loop_quit (loop);
290
+ g_source_remove (exit_timeout);
294
sig0_signal_handler (DBusGProxy *proxy,
297
@@ -1886,6 +1901,32 @@ main (int argc, char **argv)
301
+ /* Tests for a "compatibilty" object path. This is the same object as above, just
302
+ * at a different path.
304
+ proxy = dbus_g_proxy_new_for_name_owner (connection,
305
+ "org.freedesktop.DBus.GLib.TestService",
306
+ "/org/freedesktop/DBus/GLib/Tests/Compat/MyTestObjectCompat",
307
+ "org.freedesktop.DBus.GLib.Tests.MyObject",
309
+ dbus_g_proxy_add_signal (proxy, "Frobnicate", G_TYPE_INT, G_TYPE_INVALID);
311
+ dbus_g_proxy_connect_signal (proxy, "Frobnicate",
312
+ G_CALLBACK (frobnicate_signal_handler_compat),
315
+ g_print ("Calling EmitFrobnicate (compat)\n");
316
+ if (!dbus_g_proxy_call (proxy, "EmitFrobnicate", &error,
317
+ G_TYPE_INVALID, G_TYPE_INVALID))
318
+ lose_gerror ("Failed to complete EmitFrobnicate call on compat proxy", error);
320
+ g_main_loop_run (loop);
322
+ if (n_times_compat_frobnicate_received != 1)
323
+ lose ("Frobnicate signal received %d times for compat proxy, should have been 1", n_times_compat_frobnicate_received);
325
+ g_object_unref (proxy);
327
/* Test introspection */
328
proxy = dbus_g_proxy_new_for_name_owner (connection,
329
"org.freedesktop.DBus.GLib.TestService",
330
diff --git a/test/core/test-service-glib.c b/test/core/test-service-glib.c
331
index 1cdb0ac..fad2473 100644
332
--- a/test/core/test-service-glib.c
333
+++ b/test/core/test-service-glib.c
334
@@ -66,6 +66,10 @@ main (int argc, char **argv)
335
dbus_g_connection_register_g_object (connection,
336
"/org/freedesktop/DBus/GLib/Tests/MyTestObject",
338
+ /* Register a second time; we want the object to also be reachable through this interface */
339
+ dbus_g_connection_register_g_object (connection,
340
+ "/org/freedesktop/DBus/GLib/Tests/Compat/MyTestObjectCompat",
342
dbus_g_connection_register_g_object (connection,
343
"/org/freedesktop/DBus/GLib/Tests/MyTestObject2",