~ubuntu-branches/ubuntu/oneiric/dbus-glib/oneiric-updates

« back to all changes in this revision

Viewing changes to debian/patches/10_support_duplicate_object_registrations.patch

  • Committer: Bazaar Package Importer
  • Author(s): Michael Biebl
  • Date: 2009-09-29 23:49:03 UTC
  • mfrom: (1.1.7 upstream) (2.1.6 squeeze)
  • Revision ID: james.westby@ubuntu.com-20090929234903-oaprxcpac2lvd9hs
Tags: 0.82-2
* debian/patches/10_support_duplicate_object_registrations.patch
  - Pull patch from upstream git which allows duplicate object registrations
    and fixes a regression introduced in 0.82.
    (Closes: #540421, #541712, #542513, #544174, #546044)
* Bump Standards-Version to 3.8.3. No further changes.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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)
 
6
 {
 
7
   if (o->object != NULL)
 
8
     {
 
9
+      GSList *registrations;
 
10
+
 
11
+      /* Ok, the object is still around; clear out this particular registration
 
12
+       * from the registrations list.
 
13
+       */
 
14
+      registrations = g_object_steal_data (o->object, "dbus_glib_object_registrations");
 
15
+      registrations = g_slist_remove (registrations, o);
 
16
+
 
17
+      if (registrations != NULL)
 
18
+        g_object_set_data (o->object, "dbus_glib_object_registrations", registrations);
 
19
+
 
20
       g_object_weak_unref (o->object, object_registration_object_died, o);
 
21
-      g_object_steal_data (o->object, "dbus_glib_object_registration");
 
22
-      o->object = NULL;
 
23
     }
 
24
 
 
25
   g_free (o->object_path);
 
26
@@ -1741,30 +1750,19 @@ dbus_g_signal_closure_finalize (gpointer data,
 
27
 }
 
28
 
 
29
 static void
 
30
-signal_emitter_marshaller (GClosure        *closure,
 
31
-                          GValue          *retval,
 
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,
 
38
+                              GValue             *retval,
 
39
+                              guint               n_param_values,
 
40
+                              const GValue       *param_values)
 
41
 {
 
42
-  DBusGSignalClosure *sigclosure;
 
43
   DBusMessage *signal;
 
44
   DBusMessageIter iter;
 
45
   guint i;
 
46
-  const char *path;
 
47
-
 
48
-  sigclosure = (DBusGSignalClosure *) closure;
 
49
-  
 
50
-  g_assert (retval == NULL);
 
51
-
 
52
-  path = _dbus_gobject_get_path (sigclosure->object);
 
53
 
 
54
-  g_assert (path != NULL);
 
55
-
 
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);
 
62
   if (!signal)
 
63
     {
 
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++)
 
67
     {
 
68
       if (!_dbus_gvalue_marshal (&iter,
 
69
-                               (GValue *) (&(param_values[i]))))
 
70
-       {
 
71
-         g_warning ("failed to marshal parameter %d for signal %s",
 
72
-                    i, sigclosure->signame);
 
73
-         goto out;
 
74
-       }
 
75
+                                (GValue *) (&(param_values[i]))))
 
76
+        {
 
77
+          g_warning ("failed to marshal parameter %d for signal %s",
 
78
+                     i, sigclosure->signame);
 
79
+          goto out;
 
80
+        }
 
81
     }
 
82
   dbus_connection_send (DBUS_CONNECTION_FROM_G_CONNECTION (sigclosure->connection),
 
83
-                       signal, NULL);
 
84
- out:
 
85
+                        signal, NULL);
 
86
+out:
 
87
   dbus_message_unref (signal);
 
88
 }
 
89
 
 
90
 static void
 
91
+signal_emitter_marshaller (GClosure        *closure,
 
92
+                          GValue          *retval,
 
93
+                          guint            n_param_values,
 
94
+                          const GValue    *param_values,
 
95
+                          gpointer         invocation_hint,
 
96
+                          gpointer         marshal_data)
 
97
+{
 
98
+  DBusGSignalClosure *sigclosure;
 
99
+  GSList *registrations, *iter;
 
100
+
 
101
+  sigclosure = (DBusGSignalClosure *) closure;
 
102
+
 
103
+  g_assert (retval == NULL);
 
104
+
 
105
+  registrations = g_object_get_data (sigclosure->object, "dbus_glib_object_registrations");
 
106
+
 
107
+  for (iter = registrations; iter; iter = iter->next)
 
108
+    {
 
109
+      ObjectRegistration *o = iter->data;
 
110
+
 
111
+      emit_signal_for_registration (o, sigclosure, retval, n_param_values, param_values);
 
112
+    }
 
113
+}
 
114
+
 
115
+static void
 
116
 export_signals (DBusGConnection *connection, const GList *info_list, GObject *object)
 
117
 {
 
118
   GType gtype;
 
119
@@ -2092,14 +2115,24 @@ void
 
120
 dbus_g_connection_unregister_g_object (DBusGConnection *connection,
 
121
                                        GObject *object)
 
122
 {
 
123
-  ObjectRegistration *o;
 
124
+  GList *registrations, *iter;
 
125
+
 
126
+  /* Copy the list before iterating it: it will be modified in
 
127
+   * object_registration_free() each time an object path is unregistered.
 
128
+   */
 
129
+  registrations = g_list_copy (g_object_get_data (object, "dbus_glib_object_registrations"));
 
130
 
 
131
-  o = g_object_get_data (object, "dbus_glib_object_registration");
 
132
+  g_return_if_fail (registrations != NULL);
 
133
 
 
134
-  g_return_if_fail (o != NULL);
 
135
+  for (iter = registrations; iter; iter = iter->next)
 
136
+    {
 
137
+      ObjectRegistration *o = iter->data;
 
138
+      dbus_connection_unregister_object_path (DBUS_CONNECTION_FROM_G_CONNECTION (o->connection),
 
139
+          o->object_path);
 
140
+    }
 
141
 
 
142
-  dbus_connection_unregister_object_path (DBUS_CONNECTION_FROM_G_CONNECTION (o->connection),
 
143
-      o->object_path);
 
144
+  g_list_free (registrations);
 
145
+  g_assert (g_object_get_data (object, "dbus_glib_object_registrations") == NULL);
 
146
 }
 
147
 
 
148
 /**
 
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()
 
152
  * is used.
 
153
+ *
 
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.
 
156
  */
 
157
 void
 
158
 dbus_g_connection_register_g_object (DBusGConnection       *connection,
 
159
@@ -2123,28 +2159,44 @@ dbus_g_connection_register_g_object (DBusGConnection       *connection,
 
160
                                      GObject               *object)
 
161
 {
 
162
   GList *info_list;
 
163
+  GSList *registrations, *iter;
 
164
   ObjectRegistration *o;
 
165
+  gboolean is_first_registration;
 
166
 
 
167
   g_return_if_fail (connection != NULL);
 
168
   g_return_if_fail (at_path != NULL);
 
169
   g_return_if_fail (G_IS_OBJECT (object));
 
170
 
 
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");
 
175
+
 
176
+  for (iter = registrations; iter; iter = iter->next)
 
177
     {
 
178
-      g_warning ("No introspection data registered for object class \"%s\"",
 
179
-                g_type_name (G_TYPE_FROM_INSTANCE (object)));
 
180
-      return;
 
181
+      o = iter->data;
 
182
+
 
183
+      /* Silently ignore duplicate registrations */
 
184
+      if (strcmp (o->object_path, at_path) == 0)
 
185
+        return;
 
186
     }
 
187
 
 
188
-  o = g_object_get_data (object, "dbus_glib_object_registration");
 
189
+  is_first_registration = registrations == NULL;
 
190
 
 
191
-  if (o != 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.
 
195
+   */
 
196
+  if (is_first_registration)
 
197
     {
 
198
-      g_warning ("Object already registered at %s, can't re-register at %s",
 
199
-          o->object_path, at_path);
 
200
-      return;
 
201
+      info_list = lookup_object_info (object);
 
202
+      if (info_list == NULL)
 
203
+        {
 
204
+          g_warning ("No introspection data registered for object class \"%s\"",
 
205
+                     g_type_name (G_TYPE_FROM_INSTANCE (object)));
 
206
+          return;
 
207
+        }
 
208
     }
 
209
+  else
 
210
+    info_list = NULL;
 
211
 
 
212
   o = object_registration_new (connection, at_path, object);
 
213
 
 
214
@@ -2155,12 +2207,22 @@ dbus_g_connection_register_g_object (DBusGConnection       *connection,
 
215
     {
 
216
       g_error ("Failed to register GObject with DBusConnection");
 
217
       object_registration_free (o);
 
218
+      g_list_free (info_list);
 
219
       return;
 
220
     }
 
221
 
 
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)
 
226
+    {
 
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.
 
230
+       */
 
231
+      export_signals (connection, info_list, object);
 
232
+      g_list_free (info_list);
 
233
+    }
 
234
+
 
235
+  registrations = g_slist_append (registrations, o);
 
236
+  g_object_set_data (object, "dbus_glib_object_registrations", registrations);
 
237
 }
 
238
 
 
239
 /**
 
240
@@ -2539,15 +2601,20 @@ dbus_g_method_return_error (DBusGMethodInvocation *context, const GError *error)
 
241
   g_free (context);
 
242
 }
 
243
 
 
244
-const char * _dbus_gobject_get_path (GObject *obj)
 
245
+const char *
 
246
+_dbus_gobject_get_path (GObject *obj)
 
247
 {
 
248
+  GSList *registrations;
 
249
   ObjectRegistration *o;
 
250
 
 
251
-  o = g_object_get_data (obj, "dbus_glib_object_registration");
 
252
+  registrations = g_object_get_data (obj, "dbus_glib_object_registrations");
 
253
 
 
254
-  if (o == NULL)
 
255
+  if (registrations == NULL)
 
256
     return NULL;
 
257
 
 
258
+  /* First one to have been registered wins */
 
259
+  o = registrations->data;
 
260
+
 
261
   return o->object_path;
 
262
 }
 
263
 
 
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,
 
277
 }
 
278
 
 
279
 static void
 
280
+frobnicate_signal_handler_compat (DBusGProxy  *proxy,
 
281
+                                  int          val,
 
282
+                                  void        *user_data)
 
283
+{
 
284
+  n_times_compat_frobnicate_received += 1;
 
285
+
 
286
+  g_assert (val == 42);
 
287
+  g_print ("Got Frobnicate signal (compat)\n");
 
288
+
 
289
+  g_main_loop_quit (loop);
 
290
+  g_source_remove (exit_timeout);
 
291
+}
 
292
+
 
293
+static void
 
294
 sig0_signal_handler (DBusGProxy  *proxy,
 
295
                     const char  *str0,
 
296
                     int          val,
 
297
@@ -1886,6 +1901,32 @@ main (int argc, char **argv)
 
298
 
 
299
   run_mainloop ();
 
300
 
 
301
+  /* Tests for a "compatibilty" object path.  This is the same object as above, just
 
302
+   * at a different path.
 
303
+   */
 
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",
 
308
+                                           &error);
 
309
+  dbus_g_proxy_add_signal (proxy, "Frobnicate", G_TYPE_INT, G_TYPE_INVALID);
 
310
+
 
311
+  dbus_g_proxy_connect_signal (proxy, "Frobnicate",
 
312
+                               G_CALLBACK (frobnicate_signal_handler_compat),
 
313
+                               NULL, NULL);
 
314
+
 
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);
 
319
+
 
320
+  g_main_loop_run (loop);
 
321
+
 
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);
 
324
+
 
325
+  g_object_unref (proxy);
 
326
+
 
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",
 
337
                                        obj);
 
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",
 
341
+                                       obj);
 
342
   dbus_g_connection_register_g_object (connection,
 
343
                                        "/org/freedesktop/DBus/GLib/Tests/MyTestObject2",
 
344
                                        obj2);