Merge "Fix crashes in various GParamSpec creation functions" into tizen
[platform/upstream/glib.git] / gio / gdbusnameowning.c
1 /* GDBus - GLib D-Bus Library
2  *
3  * Copyright (C) 2008-2010 Red Hat, Inc.
4  *
5  * SPDX-License-Identifier: LGPL-2.1-or-later
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General
18  * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
19  *
20  * Author: David Zeuthen <davidz@redhat.com>
21  */
22
23 #include "config.h"
24
25 #include <stdlib.h>
26
27 #include "gdbusutils.h"
28 #include "gdbusnameowning.h"
29 #include "gdbuserror.h"
30 #include "gdbusprivate.h"
31 #include "gdbusconnection.h"
32
33 #include "glibintl.h"
34
35 /**
36  * SECTION:gdbusnameowning
37  * @title: Owning Bus Names
38  * @short_description: Simple API for owning bus names
39  * @include: gio/gio.h
40  *
41  * Convenience API for owning bus names.
42  *
43  * A simple example for owning a name can be found in
44  * [gdbus-example-own-name.c](https://gitlab.gnome.org/GNOME/glib/-/blob/HEAD/gio/tests/gdbus-example-own-name.c)
45  */
46
47 G_LOCK_DEFINE_STATIC (lock);
48
49 /* ---------------------------------------------------------------------------------------------------- */
50
51 typedef enum
52 {
53   PREVIOUS_CALL_NONE = 0,
54   PREVIOUS_CALL_ACQUIRED,
55   PREVIOUS_CALL_LOST,
56 } PreviousCall;
57
58 typedef struct
59 {
60   gint                      ref_count;  /* (atomic) */
61   guint                     id;
62   GBusNameOwnerFlags        flags;
63   gchar                    *name;
64   GBusAcquiredCallback      bus_acquired_handler;
65   GBusNameAcquiredCallback  name_acquired_handler;
66   GBusNameLostCallback      name_lost_handler;
67   gpointer                  user_data;
68   GDestroyNotify            user_data_free_func;
69   GMainContext             *main_context;
70
71   PreviousCall              previous_call;
72
73   GDBusConnection          *connection;
74   gulong                    disconnected_signal_handler_id;
75   guint                     name_acquired_subscription_id;
76   guint                     name_lost_subscription_id;
77
78   gboolean                  cancelled; /* must hold lock when reading or modifying */
79
80   gboolean                  needs_release;
81 } Client;
82
83 static guint next_global_id = 1;
84 static GHashTable *map_id_to_client = NULL;
85
86
87 static Client *
88 client_ref (Client *client)
89 {
90   g_atomic_int_inc (&client->ref_count);
91   return client;
92 }
93
94 static void
95 client_unref (Client *client)
96 {
97   if (g_atomic_int_dec_and_test (&client->ref_count))
98     {
99       if (client->connection != NULL)
100         {
101           if (client->disconnected_signal_handler_id > 0)
102             g_signal_handler_disconnect (client->connection, client->disconnected_signal_handler_id);
103           if (client->name_acquired_subscription_id > 0)
104             g_dbus_connection_signal_unsubscribe (client->connection, client->name_acquired_subscription_id);
105           if (client->name_lost_subscription_id > 0)
106             g_dbus_connection_signal_unsubscribe (client->connection, client->name_lost_subscription_id);
107           g_object_unref (client->connection);
108         }
109       g_main_context_unref (client->main_context);
110       g_free (client->name);
111       if (client->user_data_free_func != NULL)
112         client->user_data_free_func (client->user_data);
113       g_free (client);
114     }
115 }
116
117 /* ---------------------------------------------------------------------------------------------------- */
118
119
120 typedef enum
121 {
122   CALL_TYPE_NAME_ACQUIRED,
123   CALL_TYPE_NAME_LOST
124 } CallType;
125
126 typedef struct
127 {
128   Client *client;
129
130   /* keep this separate because client->connection may
131    * be set to NULL after scheduling the call
132    */
133   GDBusConnection *connection;
134
135   /* set to TRUE to call acquired */
136   CallType call_type;
137 } CallHandlerData;
138
139 static void
140 call_handler_data_free (CallHandlerData *data)
141 {
142   if (data->connection != NULL)
143     g_object_unref (data->connection);
144   client_unref (data->client);
145   g_free (data);
146 }
147
148 static void
149 actually_do_call (Client *client, GDBusConnection *connection, CallType call_type)
150 {
151   switch (call_type)
152     {
153     case CALL_TYPE_NAME_ACQUIRED:
154       if (client->name_acquired_handler != NULL)
155         {
156           client->name_acquired_handler (connection,
157                                          client->name,
158                                          client->user_data);
159         }
160       break;
161
162     case CALL_TYPE_NAME_LOST:
163       if (client->name_lost_handler != NULL)
164         {
165           client->name_lost_handler (connection,
166                                      client->name,
167                                      client->user_data);
168         }
169       break;
170
171     default:
172       g_assert_not_reached ();
173       break;
174     }
175 }
176
177 static gboolean
178 call_in_idle_cb (gpointer _data)
179 {
180   CallHandlerData *data = _data;
181   actually_do_call (data->client, data->connection, data->call_type);
182   return FALSE;
183 }
184
185 static void
186 schedule_call_in_idle (Client *client, CallType  call_type)
187 {
188   CallHandlerData *data;
189   GSource *idle_source;
190
191   data = g_new0 (CallHandlerData, 1);
192   data->client = client_ref (client);
193   data->connection = client->connection != NULL ? g_object_ref (client->connection) : NULL;
194   data->call_type = call_type;
195
196   idle_source = g_idle_source_new ();
197   g_source_set_priority (idle_source, G_PRIORITY_HIGH);
198   g_source_set_callback (idle_source,
199                          call_in_idle_cb,
200                          data,
201                          (GDestroyNotify) call_handler_data_free);
202   g_source_set_static_name (idle_source, "[gio, gdbusnameowning.c] call_in_idle_cb");
203   g_source_attach (idle_source, client->main_context);
204   g_source_unref (idle_source);
205 }
206
207 static void
208 do_call (Client *client, CallType call_type)
209 {
210   GMainContext *current_context;
211
212   /* only schedule in idle if we're not in the right thread */
213   current_context = g_main_context_ref_thread_default ();
214   if (current_context != client->main_context)
215     schedule_call_in_idle (client, call_type);
216   else
217     actually_do_call (client, client->connection, call_type);
218   g_main_context_unref (current_context);
219 }
220
221 static void
222 call_acquired_handler (Client *client)
223 {
224   G_LOCK (lock);
225   if (client->previous_call != PREVIOUS_CALL_ACQUIRED)
226     {
227       client->previous_call = PREVIOUS_CALL_ACQUIRED;
228       if (!client->cancelled)
229         {
230           G_UNLOCK (lock);
231           do_call (client, CALL_TYPE_NAME_ACQUIRED);
232           goto out;
233         }
234     }
235   G_UNLOCK (lock);
236  out:
237   ;
238 }
239
240 static void
241 call_lost_handler (Client  *client)
242 {
243   G_LOCK (lock);
244   if (client->previous_call != PREVIOUS_CALL_LOST)
245     {
246       client->previous_call = PREVIOUS_CALL_LOST;
247       if (!client->cancelled)
248         {
249           G_UNLOCK (lock);
250           do_call (client, CALL_TYPE_NAME_LOST);
251           goto out;
252         }
253     }
254   G_UNLOCK (lock);
255  out:
256   ;
257 }
258
259 /* ---------------------------------------------------------------------------------------------------- */
260
261 static void
262 on_name_lost_or_acquired (GDBusConnection  *connection,
263                           const gchar      *sender_name,
264                           const gchar      *object_path,
265                           const gchar      *interface_name,
266                           const gchar      *signal_name,
267                           GVariant         *parameters,
268                           gpointer          user_data)
269 {
270   Client *client = user_data;
271   const gchar *name;
272
273   if (g_strcmp0 (object_path, "/org/freedesktop/DBus") != 0 ||
274       g_strcmp0 (interface_name, "org.freedesktop.DBus") != 0 ||
275       g_strcmp0 (sender_name, "org.freedesktop.DBus") != 0)
276     goto out;
277
278   if (!g_variant_is_of_type (parameters, G_VARIANT_TYPE ("(s)")))
279     {
280       g_warning ("%s signal had unexpected signature %s", signal_name,
281                  g_variant_get_type_string (parameters));
282       goto out;
283     }
284
285   if (g_strcmp0 (signal_name, "NameLost") == 0)
286     {
287       g_variant_get (parameters, "(&s)", &name);
288       if (g_strcmp0 (name, client->name) == 0)
289         {
290           call_lost_handler (client);
291         }
292     }
293   else if (g_strcmp0 (signal_name, "NameAcquired") == 0)
294     {
295       g_variant_get (parameters, "(&s)", &name);
296       if (g_strcmp0 (name, client->name) == 0)
297         {
298           call_acquired_handler (client);
299         }
300     }
301  out:
302   ;
303 }
304
305 /* ---------------------------------------------------------------------------------------------------- */
306
307 static void
308 request_name_cb (GObject      *source_object,
309                  GAsyncResult *res,
310                  gpointer      user_data)
311 {
312   Client *client = user_data;
313   GVariant *result;
314   guint32 request_name_reply;
315   gboolean unsubscribe;
316
317   request_name_reply = 0;
318   result = NULL;
319
320   /* don't use client->connection - it may be NULL already */
321   result = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source_object),
322                                           res,
323                                           NULL);
324   if (result != NULL)
325     {
326       g_variant_get (result, "(u)", &request_name_reply);
327       g_variant_unref (result);
328     }
329
330   unsubscribe = FALSE;
331
332   switch (request_name_reply)
333     {
334     case 1: /* DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER */
335       /* We got the name - now listen for NameLost and NameAcquired */
336       call_acquired_handler (client);
337       break;
338
339     case 2: /* DBUS_REQUEST_NAME_REPLY_IN_QUEUE */
340       /* Waiting in line - listen for NameLost and NameAcquired */
341       call_lost_handler (client);
342       break;
343
344     default:
345       /* assume we couldn't get the name - explicit fallthrough */
346     case 3: /* DBUS_REQUEST_NAME_REPLY_EXISTS */
347     case 4: /* DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER */
348       /* Some other part of the process is already owning the name */
349       call_lost_handler (client);
350       unsubscribe = TRUE;
351       client->needs_release = FALSE;
352       break;
353     }
354
355   /* If we’re not the owner and not in the queue, there’s no point in continuing
356    * to listen to NameAcquired or NameLost. */
357   if (unsubscribe)
358     {
359       GDBusConnection *connection = NULL;
360
361       /* make sure we use a known good Connection object since it may be set to
362        * NULL at any point after being cancelled
363        */
364       G_LOCK (lock);
365       if (!client->cancelled)
366         connection = g_object_ref (client->connection);
367       G_UNLOCK (lock);
368
369       if (connection != NULL)
370         {
371           if (client->name_acquired_subscription_id > 0)
372             g_dbus_connection_signal_unsubscribe (client->connection, client->name_acquired_subscription_id);
373           if (client->name_lost_subscription_id > 0)
374             g_dbus_connection_signal_unsubscribe (client->connection, client->name_lost_subscription_id);
375           client->name_acquired_subscription_id = 0;
376           client->name_lost_subscription_id = 0;
377
378           g_object_unref (connection);
379         }
380     }
381
382   client_unref (client);
383 }
384
385 /* ---------------------------------------------------------------------------------------------------- */
386
387 static void
388 on_connection_disconnected (GDBusConnection *connection,
389                             gboolean         remote_peer_vanished,
390                             GError          *error,
391                             gpointer         user_data)
392 {
393   Client *client = user_data;
394
395   if (client->disconnected_signal_handler_id > 0)
396     g_signal_handler_disconnect (client->connection, client->disconnected_signal_handler_id);
397   if (client->name_acquired_subscription_id > 0)
398     g_dbus_connection_signal_unsubscribe (client->connection, client->name_acquired_subscription_id);
399   if (client->name_lost_subscription_id > 0)
400     g_dbus_connection_signal_unsubscribe (client->connection, client->name_lost_subscription_id);
401   g_object_unref (client->connection);
402   client->disconnected_signal_handler_id = 0;
403   client->name_acquired_subscription_id = 0;
404   client->name_lost_subscription_id = 0;
405   client->connection = NULL;
406
407   call_lost_handler (client);
408 }
409
410 /* ---------------------------------------------------------------------------------------------------- */
411
412 static void
413 has_connection (Client *client)
414 {
415   /* listen for disconnection */
416   client->disconnected_signal_handler_id = g_signal_connect (client->connection,
417                                                              "closed",
418                                                              G_CALLBACK (on_connection_disconnected),
419                                                              client);
420
421   /* Start listening to NameLost and NameAcquired messages. We hold
422    * references to the Client in the signal closures, since it’s possible
423    * for a signal to be in-flight after unsubscribing the signal handler.
424    * This creates a reference count cycle, but that’s explicitly broken by
425    * disconnecting the signal handlers before calling client_unref() in
426    * g_bus_unown_name().
427    *
428    * Subscribe to NameLost and NameAcquired before calling RequestName() to
429    * avoid the potential race of losing the name between receiving a reply to
430    * RequestName() and subscribing to NameLost. The #PreviousCall state will
431    * ensure that the user callbacks get called an appropriate number of times. */
432   client->name_lost_subscription_id =
433     g_dbus_connection_signal_subscribe (client->connection,
434                                         "org.freedesktop.DBus",
435                                         "org.freedesktop.DBus",
436                                         "NameLost",
437                                         "/org/freedesktop/DBus",
438                                         client->name,
439                                         G_DBUS_SIGNAL_FLAGS_NONE,
440                                         on_name_lost_or_acquired,
441                                         client_ref (client),
442                                         (GDestroyNotify) client_unref);
443   client->name_acquired_subscription_id =
444     g_dbus_connection_signal_subscribe (client->connection,
445                                         "org.freedesktop.DBus",
446                                         "org.freedesktop.DBus",
447                                         "NameAcquired",
448                                         "/org/freedesktop/DBus",
449                                         client->name,
450                                         G_DBUS_SIGNAL_FLAGS_NONE,
451                                         on_name_lost_or_acquired,
452                                         client_ref (client),
453                                         (GDestroyNotify) client_unref);
454
455   /* attempt to acquire the name */
456   client->needs_release = TRUE;
457   g_dbus_connection_call (client->connection,
458                           "org.freedesktop.DBus",  /* bus name */
459                           "/org/freedesktop/DBus", /* object path */
460                           "org.freedesktop.DBus",  /* interface name */
461                           "RequestName",           /* method name */
462                           g_variant_new ("(su)",
463                                          client->name,
464                                          client->flags),
465                           G_VARIANT_TYPE ("(u)"),
466                           G_DBUS_CALL_FLAGS_NONE,
467                           -1,
468                           NULL,
469                           (GAsyncReadyCallback) request_name_cb,
470                           client_ref (client));
471 }
472
473
474 static void
475 connection_get_cb (GObject      *source_object,
476                    GAsyncResult *res,
477                    gpointer      user_data)
478 {
479   Client *client = user_data;
480
481   /* must not do anything if already cancelled */
482   G_LOCK (lock);
483   if (client->cancelled)
484     {
485       G_UNLOCK (lock);
486       goto out;
487     }
488   G_UNLOCK (lock);
489
490   client->connection = g_bus_get_finish (res, NULL);
491   if (client->connection == NULL)
492     {
493       call_lost_handler (client);
494       goto out;
495     }
496
497   /* No need to schedule this in idle as we're already in the thread
498    * that the user called g_bus_own_name() from. This is because
499    * g_bus_get() guarantees that.
500    *
501    * Also, we need to ensure that the handler is invoked *before*
502    * we call RequestName(). Otherwise there is a race.
503    */
504   if (client->bus_acquired_handler != NULL)
505     {
506       client->bus_acquired_handler (client->connection,
507                                     client->name,
508                                     client->user_data);
509     }
510
511   has_connection (client);
512
513  out:
514   client_unref (client);
515 }
516
517 /* ---------------------------------------------------------------------------------------------------- */
518
519 /**
520  * g_bus_own_name_on_connection:
521  * @connection: a #GDBusConnection
522  * @name: the well-known name to own
523  * @flags: a set of flags from the #GBusNameOwnerFlags enumeration
524  * @name_acquired_handler: (nullable): handler to invoke when @name is acquired or %NULL
525  * @name_lost_handler: (nullable): handler to invoke when @name is lost or %NULL
526  * @user_data: user data to pass to handlers
527  * @user_data_free_func: (nullable): function for freeing @user_data or %NULL
528  *
529  * Like g_bus_own_name() but takes a #GDBusConnection instead of a
530  * #GBusType.
531  *
532  * Returns: an identifier (never 0) that can be used with
533  *     g_bus_unown_name() to stop owning the name
534  *
535  * Since: 2.26
536  */
537 guint
538 g_bus_own_name_on_connection (GDBusConnection          *connection,
539                               const gchar              *name,
540                               GBusNameOwnerFlags        flags,
541                               GBusNameAcquiredCallback  name_acquired_handler,
542                               GBusNameLostCallback      name_lost_handler,
543                               gpointer                  user_data,
544                               GDestroyNotify            user_data_free_func)
545 {
546   Client *client;
547
548   g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), 0);
549   g_return_val_if_fail (g_dbus_is_name (name) && !g_dbus_is_unique_name (name), 0);
550
551   G_LOCK (lock);
552
553   client = g_new0 (Client, 1);
554   client->ref_count = 1;
555   client->id = next_global_id++; /* TODO: uh oh, handle overflow */
556   client->name = g_strdup (name);
557   client->flags = flags;
558   client->name_acquired_handler = name_acquired_handler;
559   client->name_lost_handler = name_lost_handler;
560   client->user_data = user_data;
561   client->user_data_free_func = user_data_free_func;
562   client->main_context = g_main_context_ref_thread_default ();
563
564   client->connection = g_object_ref (connection);
565
566   if (map_id_to_client == NULL)
567     {
568       map_id_to_client = g_hash_table_new (g_direct_hash, g_direct_equal);
569     }
570   g_hash_table_insert (map_id_to_client,
571                        GUINT_TO_POINTER (client->id),
572                        client);
573
574   G_UNLOCK (lock);
575
576   has_connection (client);
577
578   return client->id;
579 }
580
581 /**
582  * g_bus_own_name:
583  * @bus_type: the type of bus to own a name on
584  * @name: the well-known name to own
585  * @flags: a set of flags from the #GBusNameOwnerFlags enumeration
586  * @bus_acquired_handler: (nullable): handler to invoke when connected to the bus of type @bus_type or %NULL
587  * @name_acquired_handler: (nullable): handler to invoke when @name is acquired or %NULL
588  * @name_lost_handler: (nullable): handler to invoke when @name is lost or %NULL
589  * @user_data: user data to pass to handlers
590  * @user_data_free_func: (nullable): function for freeing @user_data or %NULL
591  *
592  * Starts acquiring @name on the bus specified by @bus_type and calls
593  * @name_acquired_handler and @name_lost_handler when the name is
594  * acquired respectively lost. Callbacks will be invoked in the 
595  * [thread-default main context][g-main-context-push-thread-default]
596  * of the thread you are calling this function from.
597  *
598  * You are guaranteed that one of the @name_acquired_handler and @name_lost_handler
599  * callbacks will be invoked after calling this function - there are three
600  * possible cases:
601  * 
602  * - @name_lost_handler with a %NULL connection (if a connection to the bus
603  *   can't be made).
604  *
605  * - @bus_acquired_handler then @name_lost_handler (if the name can't be
606  *   obtained)
607  *
608  * - @bus_acquired_handler then @name_acquired_handler (if the name was
609  *   obtained).
610  *
611  * When you are done owning the name, just call g_bus_unown_name()
612  * with the owner id this function returns.
613  *
614  * If the name is acquired or lost (for example another application
615  * could acquire the name if you allow replacement or the application
616  * currently owning the name exits), the handlers are also invoked.
617  * If the #GDBusConnection that is used for attempting to own the name
618  * closes, then @name_lost_handler is invoked since it is no longer
619  * possible for other processes to access the process.
620  *
621  * You cannot use g_bus_own_name() several times for the same name (unless
622  * interleaved with calls to g_bus_unown_name()) - only the first call
623  * will work.
624  *
625  * Another guarantee is that invocations of @name_acquired_handler
626  * and @name_lost_handler are guaranteed to alternate; that
627  * is, if @name_acquired_handler is invoked then you are
628  * guaranteed that the next time one of the handlers is invoked, it
629  * will be @name_lost_handler. The reverse is also true.
630  *
631  * If you plan on exporting objects (using e.g.
632  * g_dbus_connection_register_object()), note that it is generally too late
633  * to export the objects in @name_acquired_handler. Instead, you can do this
634  * in @bus_acquired_handler since you are guaranteed that this will run
635  * before @name is requested from the bus.
636  *
637  * This behavior makes it very simple to write applications that wants
638  * to [own names][gdbus-owning-names] and export objects.
639  * Simply register objects to be exported in @bus_acquired_handler and
640  * unregister the objects (if any) in @name_lost_handler.
641  *
642  * Returns: an identifier (never 0) that can be used with
643  *     g_bus_unown_name() to stop owning the name.
644  *
645  * Since: 2.26
646  */
647 guint
648 g_bus_own_name (GBusType                  bus_type,
649                 const gchar              *name,
650                 GBusNameOwnerFlags        flags,
651                 GBusAcquiredCallback      bus_acquired_handler,
652                 GBusNameAcquiredCallback  name_acquired_handler,
653                 GBusNameLostCallback      name_lost_handler,
654                 gpointer                  user_data,
655                 GDestroyNotify            user_data_free_func)
656 {
657   Client *client;
658
659   g_return_val_if_fail (g_dbus_is_name (name) && !g_dbus_is_unique_name (name), 0);
660
661   G_LOCK (lock);
662
663   client = g_new0 (Client, 1);
664   client->ref_count = 1;
665   client->id = next_global_id++; /* TODO: uh oh, handle overflow */
666   client->name = g_strdup (name);
667   client->flags = flags;
668   client->bus_acquired_handler = bus_acquired_handler;
669   client->name_acquired_handler = name_acquired_handler;
670   client->name_lost_handler = name_lost_handler;
671   client->user_data = user_data;
672   client->user_data_free_func = user_data_free_func;
673   client->main_context = g_main_context_ref_thread_default ();
674
675   if (map_id_to_client == NULL)
676     {
677       map_id_to_client = g_hash_table_new (g_direct_hash, g_direct_equal);
678     }
679   g_hash_table_insert (map_id_to_client,
680                        GUINT_TO_POINTER (client->id),
681                        client);
682
683   g_bus_get (bus_type,
684              NULL,
685              connection_get_cb,
686              client_ref (client));
687
688   G_UNLOCK (lock);
689
690   return client->id;
691 }
692
693 typedef struct {
694   GClosure *bus_acquired_closure;
695   GClosure *name_acquired_closure;
696   GClosure *name_lost_closure;
697 } OwnNameData;
698
699 static OwnNameData *
700 own_name_data_new (GClosure *bus_acquired_closure,
701                    GClosure *name_acquired_closure,
702                    GClosure *name_lost_closure)
703 {
704   OwnNameData *data;
705
706   data = g_new0 (OwnNameData, 1);
707
708   if (bus_acquired_closure != NULL)
709     {
710       data->bus_acquired_closure = g_closure_ref (bus_acquired_closure);
711       g_closure_sink (bus_acquired_closure);
712       if (G_CLOSURE_NEEDS_MARSHAL (bus_acquired_closure))
713         g_closure_set_marshal (bus_acquired_closure, g_cclosure_marshal_generic);
714     }
715
716   if (name_acquired_closure != NULL)
717     {
718       data->name_acquired_closure = g_closure_ref (name_acquired_closure);
719       g_closure_sink (name_acquired_closure);
720       if (G_CLOSURE_NEEDS_MARSHAL (name_acquired_closure))
721         g_closure_set_marshal (name_acquired_closure, g_cclosure_marshal_generic);
722     }
723
724   if (name_lost_closure != NULL)
725     {
726       data->name_lost_closure = g_closure_ref (name_lost_closure);
727       g_closure_sink (name_lost_closure);
728       if (G_CLOSURE_NEEDS_MARSHAL (name_lost_closure))
729         g_closure_set_marshal (name_lost_closure, g_cclosure_marshal_generic);
730     }
731
732   return data;
733 }
734
735 static void
736 own_with_closures_on_bus_acquired (GDBusConnection *connection,
737                                    const gchar     *name,
738                                    gpointer         user_data)
739 {
740   OwnNameData *data = user_data;
741   GValue params[2] = { G_VALUE_INIT, G_VALUE_INIT };
742
743   g_value_init (&params[0], G_TYPE_DBUS_CONNECTION);
744   g_value_set_object (&params[0], connection);
745
746   g_value_init (&params[1], G_TYPE_STRING);
747   g_value_set_string (&params[1], name);
748
749   g_closure_invoke (data->bus_acquired_closure, NULL, 2, params, NULL);
750
751   g_value_unset (params + 0);
752   g_value_unset (params + 1);
753 }
754
755 static void
756 own_with_closures_on_name_acquired (GDBusConnection *connection,
757                                     const gchar     *name,
758                                     gpointer         user_data)
759 {
760   OwnNameData *data = user_data;
761   GValue params[2] = { G_VALUE_INIT, G_VALUE_INIT };
762
763   g_value_init (&params[0], G_TYPE_DBUS_CONNECTION);
764   g_value_set_object (&params[0], connection);
765
766   g_value_init (&params[1], G_TYPE_STRING);
767   g_value_set_string (&params[1], name);
768
769   g_closure_invoke (data->name_acquired_closure, NULL, 2, params, NULL);
770
771   g_value_unset (params + 0);
772   g_value_unset (params + 1);
773 }
774
775 static void
776 own_with_closures_on_name_lost (GDBusConnection *connection,
777                                 const gchar     *name,
778                                 gpointer         user_data)
779 {
780   OwnNameData *data = user_data;
781   GValue params[2] = { G_VALUE_INIT, G_VALUE_INIT };
782
783   g_value_init (&params[0], G_TYPE_DBUS_CONNECTION);
784   g_value_set_object (&params[0], connection);
785
786   g_value_init (&params[1], G_TYPE_STRING);
787   g_value_set_string (&params[1], name);
788
789   g_closure_invoke (data->name_lost_closure, NULL, 2, params, NULL);
790
791   g_value_unset (params + 0);
792   g_value_unset (params + 1);
793 }
794
795 static void
796 bus_own_name_free_func (gpointer user_data)
797 {
798   OwnNameData *data = user_data;
799
800   if (data->bus_acquired_closure != NULL)
801     g_closure_unref (data->bus_acquired_closure);
802
803   if (data->name_acquired_closure != NULL)
804     g_closure_unref (data->name_acquired_closure);
805
806   if (data->name_lost_closure != NULL)
807     g_closure_unref (data->name_lost_closure);
808
809   g_free (data);
810 }
811
812 /**
813  * g_bus_own_name_with_closures: (rename-to g_bus_own_name)
814  * @bus_type: the type of bus to own a name on
815  * @name: the well-known name to own
816  * @flags: a set of flags from the #GBusNameOwnerFlags enumeration
817  * @bus_acquired_closure: (nullable): #GClosure to invoke when connected to
818  *     the bus of type @bus_type or %NULL
819  * @name_acquired_closure: (nullable): #GClosure to invoke when @name is
820  *     acquired or %NULL
821  * @name_lost_closure: (nullable): #GClosure to invoke when @name is lost or
822  *     %NULL
823  *
824  * Version of g_bus_own_name() using closures instead of callbacks for
825  * easier binding in other languages.
826  *
827  * Returns: an identifier (never 0) that can be used with
828  *     g_bus_unown_name() to stop owning the name.
829  *
830  * Since: 2.26
831  */
832 guint
833 g_bus_own_name_with_closures (GBusType            bus_type,
834                               const gchar        *name,
835                               GBusNameOwnerFlags  flags,
836                               GClosure           *bus_acquired_closure,
837                               GClosure           *name_acquired_closure,
838                               GClosure           *name_lost_closure)
839 {
840   return g_bus_own_name (bus_type,
841           name,
842           flags,
843           bus_acquired_closure != NULL ? own_with_closures_on_bus_acquired : NULL,
844           name_acquired_closure != NULL ? own_with_closures_on_name_acquired : NULL,
845           name_lost_closure != NULL ? own_with_closures_on_name_lost : NULL,
846           own_name_data_new (bus_acquired_closure,
847                              name_acquired_closure,
848                              name_lost_closure),
849           bus_own_name_free_func);
850 }
851
852 /**
853  * g_bus_own_name_on_connection_with_closures: (rename-to g_bus_own_name_on_connection)
854  * @connection: a #GDBusConnection
855  * @name: the well-known name to own
856  * @flags: a set of flags from the #GBusNameOwnerFlags enumeration
857  * @name_acquired_closure: (nullable): #GClosure to invoke when @name is
858  *     acquired or %NULL
859  * @name_lost_closure: (nullable): #GClosure to invoke when @name is lost
860  *     or %NULL
861  *
862  * Version of g_bus_own_name_on_connection() using closures instead of
863  * callbacks for easier binding in other languages.
864  *
865  * Returns: an identifier (never 0) that can be used with
866  *     g_bus_unown_name() to stop owning the name.
867  *
868  * Since: 2.26
869  */
870 guint
871 g_bus_own_name_on_connection_with_closures (GDBusConnection    *connection,
872                                             const gchar        *name,
873                                             GBusNameOwnerFlags  flags,
874                                             GClosure           *name_acquired_closure,
875                                             GClosure           *name_lost_closure)
876 {
877   return g_bus_own_name_on_connection (connection,
878           name,
879           flags,
880           name_acquired_closure != NULL ? own_with_closures_on_name_acquired : NULL,
881           name_lost_closure != NULL ? own_with_closures_on_name_lost : NULL,
882           own_name_data_new (NULL,
883                              name_acquired_closure,
884                              name_lost_closure),
885           bus_own_name_free_func);
886 }
887
888 /**
889  * g_bus_unown_name:
890  * @owner_id: an identifier obtained from g_bus_own_name()
891  *
892  * Stops owning a name.
893  *
894  * Note that there may still be D-Bus traffic to process (relating to owning
895  * and unowning the name) in the current thread-default #GMainContext after
896  * this function has returned. You should continue to iterate the #GMainContext
897  * until the #GDestroyNotify function passed to g_bus_own_name() is called, in
898  * order to avoid memory leaks through callbacks queued on the #GMainContext
899  * after it’s stopped being iterated.
900  *
901  * Since: 2.26
902  */
903 void
904 g_bus_unown_name (guint owner_id)
905 {
906   Client *client;
907
908   g_return_if_fail (owner_id > 0);
909
910   client = NULL;
911
912   G_LOCK (lock);
913   if (owner_id == 0 || map_id_to_client == NULL ||
914       (client = g_hash_table_lookup (map_id_to_client, GUINT_TO_POINTER (owner_id))) == NULL)
915     {
916       g_warning ("Invalid id %d passed to g_bus_unown_name()", owner_id);
917       goto out;
918     }
919
920   client->cancelled = TRUE;
921   g_warn_if_fail (g_hash_table_remove (map_id_to_client, GUINT_TO_POINTER (owner_id)));
922
923  out:
924   G_UNLOCK (lock);
925
926   /* do callback without holding lock */
927   if (client != NULL)
928     {
929       /* Release the name if needed */
930       if (client->needs_release &&
931           client->connection != NULL &&
932           !g_dbus_connection_is_closed (client->connection))
933         {
934           GVariant *result;
935           GError *error;
936           guint32 release_name_reply;
937
938           /* TODO: it kinda sucks having to do a sync call to release the name - but if
939            * we don't, then a subsequent grab of the name will make the bus daemon return
940            * IN_QUEUE which will trigger name_lost().
941            *
942            * I believe this is a bug in the bus daemon.
943            */
944           error = NULL;
945           result = g_dbus_connection_call_sync (client->connection,
946                                                 "org.freedesktop.DBus",  /* bus name */
947                                                 "/org/freedesktop/DBus", /* object path */
948                                                 "org.freedesktop.DBus",  /* interface name */
949                                                 "ReleaseName",           /* method name */
950                                                 g_variant_new ("(s)", client->name),
951                                                 G_VARIANT_TYPE ("(u)"),
952                                                 G_DBUS_CALL_FLAGS_NONE,
953                                                 -1,
954                                                 NULL,
955                                                 &error);
956           if (result == NULL)
957             {
958               g_warning ("Error releasing name %s: %s", client->name, error->message);
959               g_error_free (error);
960             }
961           else
962             {
963               g_variant_get (result, "(u)", &release_name_reply);
964               if (release_name_reply != 1 /* DBUS_RELEASE_NAME_REPLY_RELEASED */)
965                 {
966                   g_warning ("Unexpected reply %d when releasing name %s", release_name_reply, client->name);
967                 }
968               else
969                 {
970                   client->needs_release = FALSE;
971                 }
972               g_variant_unref (result);
973             }
974         }
975
976       if (client->disconnected_signal_handler_id > 0)
977         g_signal_handler_disconnect (client->connection, client->disconnected_signal_handler_id);
978       if (client->name_acquired_subscription_id > 0)
979         g_dbus_connection_signal_unsubscribe (client->connection, client->name_acquired_subscription_id);
980       if (client->name_lost_subscription_id > 0)
981         g_dbus_connection_signal_unsubscribe (client->connection, client->name_lost_subscription_id);
982       client->disconnected_signal_handler_id = 0;
983       client->name_acquired_subscription_id = 0;
984       client->name_lost_subscription_id = 0;
985       if (client->connection != NULL)
986         {
987           g_object_unref (client->connection);
988           client->connection = NULL;
989         }
990
991       client_unref (client);
992     }
993 }