Add some more cases to the app-id unit tests
[glib.git] / gio / gdbusnameowning.c
blobc95e434901ab694dc345ac1d2c3848384f7f4d23
1 /* GDBus - GLib D-Bus Library
3 * Copyright (C) 2008-2010 Red Hat, Inc.
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General
16 * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
18 * Author: David Zeuthen <davidz@redhat.com>
21 #include "config.h"
23 #include <stdlib.h>
25 #include "gdbusutils.h"
26 #include "gdbusnameowning.h"
27 #include "gdbuserror.h"
28 #include "gdbusprivate.h"
29 #include "gdbusconnection.h"
31 #include "glibintl.h"
33 /**
34 * SECTION:gdbusnameowning
35 * @title: Owning Bus Names
36 * @short_description: Simple API for owning bus names
37 * @include: gio/gio.h
39 * Convenience API for owning bus names.
41 * A simple example for owning a name can be found in
42 * [gdbus-example-own-name.c](https://git.gnome.org/browse/glib/tree/gio/tests/gdbus-example-own-name.c)
45 G_LOCK_DEFINE_STATIC (lock);
47 /* ---------------------------------------------------------------------------------------------------- */
49 typedef enum
51 PREVIOUS_CALL_NONE = 0,
52 PREVIOUS_CALL_ACQUIRED,
53 PREVIOUS_CALL_LOST,
54 } PreviousCall;
56 typedef struct
58 volatile gint ref_count;
59 guint id;
60 GBusNameOwnerFlags flags;
61 gchar *name;
62 GBusAcquiredCallback bus_acquired_handler;
63 GBusNameAcquiredCallback name_acquired_handler;
64 GBusNameLostCallback name_lost_handler;
65 gpointer user_data;
66 GDestroyNotify user_data_free_func;
67 GMainContext *main_context;
69 PreviousCall previous_call;
71 GDBusConnection *connection;
72 gulong disconnected_signal_handler_id;
73 guint name_acquired_subscription_id;
74 guint name_lost_subscription_id;
76 volatile gboolean cancelled; /* must hold lock when reading or modifying */
78 gboolean needs_release;
79 } Client;
81 static guint next_global_id = 1;
82 static GHashTable *map_id_to_client = NULL;
85 static Client *
86 client_ref (Client *client)
88 g_atomic_int_inc (&client->ref_count);
89 return client;
92 static void
93 client_unref (Client *client)
95 if (g_atomic_int_dec_and_test (&client->ref_count))
97 if (client->connection != NULL)
99 if (client->disconnected_signal_handler_id > 0)
100 g_signal_handler_disconnect (client->connection, client->disconnected_signal_handler_id);
101 if (client->name_acquired_subscription_id > 0)
102 g_dbus_connection_signal_unsubscribe (client->connection, client->name_acquired_subscription_id);
103 if (client->name_lost_subscription_id > 0)
104 g_dbus_connection_signal_unsubscribe (client->connection, client->name_lost_subscription_id);
105 g_object_unref (client->connection);
107 g_main_context_unref (client->main_context);
108 g_free (client->name);
109 if (client->user_data_free_func != NULL)
110 client->user_data_free_func (client->user_data);
111 g_free (client);
115 /* ---------------------------------------------------------------------------------------------------- */
118 typedef enum
120 CALL_TYPE_NAME_ACQUIRED,
121 CALL_TYPE_NAME_LOST
122 } CallType;
124 typedef struct
126 Client *client;
128 /* keep this separate because client->connection may
129 * be set to NULL after scheduling the call
131 GDBusConnection *connection;
133 /* set to TRUE to call acquired */
134 CallType call_type;
135 } CallHandlerData;
137 static void
138 call_handler_data_free (CallHandlerData *data)
140 if (data->connection != NULL)
141 g_object_unref (data->connection);
142 client_unref (data->client);
143 g_free (data);
146 static void
147 actually_do_call (Client *client, GDBusConnection *connection, CallType call_type)
149 switch (call_type)
151 case CALL_TYPE_NAME_ACQUIRED:
152 if (client->name_acquired_handler != NULL)
154 client->name_acquired_handler (connection,
155 client->name,
156 client->user_data);
158 break;
160 case CALL_TYPE_NAME_LOST:
161 if (client->name_lost_handler != NULL)
163 client->name_lost_handler (connection,
164 client->name,
165 client->user_data);
167 break;
169 default:
170 g_assert_not_reached ();
171 break;
175 static gboolean
176 call_in_idle_cb (gpointer _data)
178 CallHandlerData *data = _data;
179 actually_do_call (data->client, data->connection, data->call_type);
180 return FALSE;
183 static void
184 schedule_call_in_idle (Client *client, CallType call_type)
186 CallHandlerData *data;
187 GSource *idle_source;
189 data = g_new0 (CallHandlerData, 1);
190 data->client = client_ref (client);
191 data->connection = client->connection != NULL ? g_object_ref (client->connection) : NULL;
192 data->call_type = call_type;
194 idle_source = g_idle_source_new ();
195 g_source_set_priority (idle_source, G_PRIORITY_HIGH);
196 g_source_set_callback (idle_source,
197 call_in_idle_cb,
198 data,
199 (GDestroyNotify) call_handler_data_free);
200 g_source_set_name (idle_source, "[gio] call_in_idle_cb");
201 g_source_attach (idle_source, client->main_context);
202 g_source_unref (idle_source);
205 static void
206 do_call (Client *client, CallType call_type)
208 GMainContext *current_context;
210 /* only schedule in idle if we're not in the right thread */
211 current_context = g_main_context_ref_thread_default ();
212 if (current_context != client->main_context)
213 schedule_call_in_idle (client, call_type);
214 else
215 actually_do_call (client, client->connection, call_type);
216 g_main_context_unref (current_context);
219 static void
220 call_acquired_handler (Client *client)
222 G_LOCK (lock);
223 if (client->previous_call != PREVIOUS_CALL_ACQUIRED)
225 client->previous_call = PREVIOUS_CALL_ACQUIRED;
226 if (!client->cancelled)
228 G_UNLOCK (lock);
229 do_call (client, CALL_TYPE_NAME_ACQUIRED);
230 goto out;
233 G_UNLOCK (lock);
234 out:
238 static void
239 call_lost_handler (Client *client)
241 G_LOCK (lock);
242 if (client->previous_call != PREVIOUS_CALL_LOST)
244 client->previous_call = PREVIOUS_CALL_LOST;
245 if (!client->cancelled)
247 G_UNLOCK (lock);
248 do_call (client, CALL_TYPE_NAME_LOST);
249 goto out;
252 G_UNLOCK (lock);
253 out:
257 /* ---------------------------------------------------------------------------------------------------- */
259 static void
260 on_name_lost_or_acquired (GDBusConnection *connection,
261 const gchar *sender_name,
262 const gchar *object_path,
263 const gchar *interface_name,
264 const gchar *signal_name,
265 GVariant *parameters,
266 gpointer user_data)
268 Client *client = user_data;
269 const gchar *name;
271 if (g_strcmp0 (object_path, "/org/freedesktop/DBus") != 0 ||
272 g_strcmp0 (interface_name, "org.freedesktop.DBus") != 0 ||
273 g_strcmp0 (sender_name, "org.freedesktop.DBus") != 0)
274 goto out;
276 if (g_strcmp0 (signal_name, "NameLost") == 0)
278 g_variant_get (parameters, "(&s)", &name);
279 if (g_strcmp0 (name, client->name) == 0)
281 call_lost_handler (client);
284 else if (g_strcmp0 (signal_name, "NameAcquired") == 0)
286 g_variant_get (parameters, "(&s)", &name);
287 if (g_strcmp0 (name, client->name) == 0)
289 call_acquired_handler (client);
292 out:
296 /* ---------------------------------------------------------------------------------------------------- */
298 static void
299 request_name_cb (GObject *source_object,
300 GAsyncResult *res,
301 gpointer user_data)
303 Client *client = user_data;
304 GVariant *result;
305 guint32 request_name_reply;
306 gboolean subscribe;
308 request_name_reply = 0;
309 result = NULL;
311 /* don't use client->connection - it may be NULL already */
312 result = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source_object),
313 res,
314 NULL);
315 if (result != NULL)
317 g_variant_get (result, "(u)", &request_name_reply);
318 g_variant_unref (result);
321 subscribe = FALSE;
323 switch (request_name_reply)
325 case 1: /* DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER */
326 /* We got the name - now listen for NameLost and NameAcquired */
327 call_acquired_handler (client);
328 subscribe = TRUE;
329 client->needs_release = TRUE;
330 break;
332 case 2: /* DBUS_REQUEST_NAME_REPLY_IN_QUEUE */
333 /* Waiting in line - listen for NameLost and NameAcquired */
334 call_lost_handler (client);
335 subscribe = TRUE;
336 client->needs_release = TRUE;
337 break;
339 default:
340 /* assume we couldn't get the name - explicit fallthrough */
341 case 3: /* DBUS_REQUEST_NAME_REPLY_EXISTS */
342 case 4: /* DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER */
343 /* Some other part of the process is already owning the name */
344 call_lost_handler (client);
345 break;
349 if (subscribe)
351 GDBusConnection *connection = NULL;
353 /* if cancelled, there is no point in subscribing to signals - if not, make sure
354 * we use a known good Connection object since it may be set to NULL at any point
355 * after being cancelled
357 G_LOCK (lock);
358 if (!client->cancelled)
359 connection = g_object_ref (client->connection);
360 G_UNLOCK (lock);
362 /* start listening to NameLost and NameAcquired messages */
363 if (connection != NULL)
365 client->name_lost_subscription_id =
366 g_dbus_connection_signal_subscribe (connection,
367 "org.freedesktop.DBus",
368 "org.freedesktop.DBus",
369 "NameLost",
370 "/org/freedesktop/DBus",
371 client->name,
372 G_DBUS_SIGNAL_FLAGS_NONE,
373 on_name_lost_or_acquired,
374 client,
375 NULL);
376 client->name_acquired_subscription_id =
377 g_dbus_connection_signal_subscribe (connection,
378 "org.freedesktop.DBus",
379 "org.freedesktop.DBus",
380 "NameAcquired",
381 "/org/freedesktop/DBus",
382 client->name,
383 G_DBUS_SIGNAL_FLAGS_NONE,
384 on_name_lost_or_acquired,
385 client,
386 NULL);
387 g_object_unref (connection);
391 client_unref (client);
394 /* ---------------------------------------------------------------------------------------------------- */
396 static void
397 on_connection_disconnected (GDBusConnection *connection,
398 gboolean remote_peer_vanished,
399 GError *error,
400 gpointer user_data)
402 Client *client = user_data;
404 if (client->disconnected_signal_handler_id > 0)
405 g_signal_handler_disconnect (client->connection, client->disconnected_signal_handler_id);
406 if (client->name_acquired_subscription_id > 0)
407 g_dbus_connection_signal_unsubscribe (client->connection, client->name_acquired_subscription_id);
408 if (client->name_lost_subscription_id > 0)
409 g_dbus_connection_signal_unsubscribe (client->connection, client->name_lost_subscription_id);
410 g_object_unref (client->connection);
411 client->disconnected_signal_handler_id = 0;
412 client->name_acquired_subscription_id = 0;
413 client->name_lost_subscription_id = 0;
414 client->connection = NULL;
416 call_lost_handler (client);
419 /* ---------------------------------------------------------------------------------------------------- */
421 static void
422 has_connection (Client *client)
424 /* listen for disconnection */
425 client->disconnected_signal_handler_id = g_signal_connect (client->connection,
426 "closed",
427 G_CALLBACK (on_connection_disconnected),
428 client);
430 /* attempt to acquire the name */
431 g_dbus_connection_call (client->connection,
432 "org.freedesktop.DBus", /* bus name */
433 "/org/freedesktop/DBus", /* object path */
434 "org.freedesktop.DBus", /* interface name */
435 "RequestName", /* method name */
436 g_variant_new ("(su)",
437 client->name,
438 client->flags),
439 G_VARIANT_TYPE ("(u)"),
440 G_DBUS_CALL_FLAGS_NONE,
442 NULL,
443 (GAsyncReadyCallback) request_name_cb,
444 client_ref (client));
448 static void
449 connection_get_cb (GObject *source_object,
450 GAsyncResult *res,
451 gpointer user_data)
453 Client *client = user_data;
455 /* must not do anything if already cancelled */
456 G_LOCK (lock);
457 if (client->cancelled)
459 G_UNLOCK (lock);
460 goto out;
462 G_UNLOCK (lock);
464 client->connection = g_bus_get_finish (res, NULL);
465 if (client->connection == NULL)
467 call_lost_handler (client);
468 goto out;
471 /* No need to schedule this in idle as we're already in the thread
472 * that the user called g_bus_own_name() from. This is because
473 * g_bus_get() guarantees that.
475 * Also, we need to ensure that the handler is invoked *before*
476 * we call RequestName(). Otherwise there is a race.
478 if (client->bus_acquired_handler != NULL)
480 client->bus_acquired_handler (client->connection,
481 client->name,
482 client->user_data);
485 has_connection (client);
487 out:
488 client_unref (client);
491 /* ---------------------------------------------------------------------------------------------------- */
494 * g_bus_own_name_on_connection:
495 * @connection: a #GDBusConnection
496 * @name: the well-known name to own
497 * @flags: a set of flags from the #GBusNameOwnerFlags enumeration
498 * @name_acquired_handler: (nullable): handler to invoke when @name is acquired or %NULL
499 * @name_lost_handler: (nullable): handler to invoke when @name is lost or %NULL
500 * @user_data: user data to pass to handlers
501 * @user_data_free_func: (nullable): function for freeing @user_data or %NULL
503 * Like g_bus_own_name() but takes a #GDBusConnection instead of a
504 * #GBusType.
506 * Returns: an identifier (never 0) that an be used with
507 * g_bus_unown_name() to stop owning the name
509 * Since: 2.26
511 guint
512 g_bus_own_name_on_connection (GDBusConnection *connection,
513 const gchar *name,
514 GBusNameOwnerFlags flags,
515 GBusNameAcquiredCallback name_acquired_handler,
516 GBusNameLostCallback name_lost_handler,
517 gpointer user_data,
518 GDestroyNotify user_data_free_func)
520 Client *client;
522 g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), 0);
523 g_return_val_if_fail (g_dbus_is_name (name) && !g_dbus_is_unique_name (name), 0);
525 G_LOCK (lock);
527 client = g_new0 (Client, 1);
528 client->ref_count = 1;
529 client->id = next_global_id++; /* TODO: uh oh, handle overflow */
530 client->name = g_strdup (name);
531 client->flags = flags;
532 client->name_acquired_handler = name_acquired_handler;
533 client->name_lost_handler = name_lost_handler;
534 client->user_data = user_data;
535 client->user_data_free_func = user_data_free_func;
536 client->main_context = g_main_context_ref_thread_default ();
538 client->connection = g_object_ref (connection);
540 if (map_id_to_client == NULL)
542 map_id_to_client = g_hash_table_new (g_direct_hash, g_direct_equal);
544 g_hash_table_insert (map_id_to_client,
545 GUINT_TO_POINTER (client->id),
546 client);
548 G_UNLOCK (lock);
550 has_connection (client);
552 return client->id;
556 * g_bus_own_name:
557 * @bus_type: the type of bus to own a name on
558 * @name: the well-known name to own
559 * @flags: a set of flags from the #GBusNameOwnerFlags enumeration
560 * @bus_acquired_handler: (nullable): handler to invoke when connected to the bus of type @bus_type or %NULL
561 * @name_acquired_handler: (nullable): handler to invoke when @name is acquired or %NULL
562 * @name_lost_handler: (nullable): handler to invoke when @name is lost or %NULL
563 * @user_data: user data to pass to handlers
564 * @user_data_free_func: (nullable): function for freeing @user_data or %NULL
566 * Starts acquiring @name on the bus specified by @bus_type and calls
567 * @name_acquired_handler and @name_lost_handler when the name is
568 * acquired respectively lost. Callbacks will be invoked in the
569 * [thread-default main context][g-main-context-push-thread-default]
570 * of the thread you are calling this function from.
572 * You are guaranteed that one of the @name_acquired_handler and @name_lost_handler
573 * callbacks will be invoked after calling this function - there are three
574 * possible cases:
576 * - @name_lost_handler with a %NULL connection (if a connection to the bus
577 * can't be made).
579 * - @bus_acquired_handler then @name_lost_handler (if the name can't be
580 * obtained)
582 * - @bus_acquired_handler then @name_acquired_handler (if the name was
583 * obtained).
585 * When you are done owning the name, just call g_bus_unown_name()
586 * with the owner id this function returns.
588 * If the name is acquired or lost (for example another application
589 * could acquire the name if you allow replacement or the application
590 * currently owning the name exits), the handlers are also invoked.
591 * If the #GDBusConnection that is used for attempting to own the name
592 * closes, then @name_lost_handler is invoked since it is no longer
593 * possible for other processes to access the process.
595 * You cannot use g_bus_own_name() several times for the same name (unless
596 * interleaved with calls to g_bus_unown_name()) - only the first call
597 * will work.
599 * Another guarantee is that invocations of @name_acquired_handler
600 * and @name_lost_handler are guaranteed to alternate; that
601 * is, if @name_acquired_handler is invoked then you are
602 * guaranteed that the next time one of the handlers is invoked, it
603 * will be @name_lost_handler. The reverse is also true.
605 * If you plan on exporting objects (using e.g.
606 * g_dbus_connection_register_object()), note that it is generally too late
607 * to export the objects in @name_acquired_handler. Instead, you can do this
608 * in @bus_acquired_handler since you are guaranteed that this will run
609 * before @name is requested from the bus.
611 * This behavior makes it very simple to write applications that wants
612 * to [own names][gdbus-owning-names] and export objects.
613 * Simply register objects to be exported in @bus_acquired_handler and
614 * unregister the objects (if any) in @name_lost_handler.
616 * Returns: an identifier (never 0) that an be used with
617 * g_bus_unown_name() to stop owning the name.
619 * Since: 2.26
621 guint
622 g_bus_own_name (GBusType bus_type,
623 const gchar *name,
624 GBusNameOwnerFlags flags,
625 GBusAcquiredCallback bus_acquired_handler,
626 GBusNameAcquiredCallback name_acquired_handler,
627 GBusNameLostCallback name_lost_handler,
628 gpointer user_data,
629 GDestroyNotify user_data_free_func)
631 Client *client;
633 g_return_val_if_fail (g_dbus_is_name (name) && !g_dbus_is_unique_name (name), 0);
635 G_LOCK (lock);
637 client = g_new0 (Client, 1);
638 client->ref_count = 1;
639 client->id = next_global_id++; /* TODO: uh oh, handle overflow */
640 client->name = g_strdup (name);
641 client->flags = flags;
642 client->bus_acquired_handler = bus_acquired_handler;
643 client->name_acquired_handler = name_acquired_handler;
644 client->name_lost_handler = name_lost_handler;
645 client->user_data = user_data;
646 client->user_data_free_func = user_data_free_func;
647 client->main_context = g_main_context_ref_thread_default ();
649 if (map_id_to_client == NULL)
651 map_id_to_client = g_hash_table_new (g_direct_hash, g_direct_equal);
653 g_hash_table_insert (map_id_to_client,
654 GUINT_TO_POINTER (client->id),
655 client);
657 g_bus_get (bus_type,
658 NULL,
659 connection_get_cb,
660 client_ref (client));
662 G_UNLOCK (lock);
664 return client->id;
667 typedef struct {
668 GClosure *bus_acquired_closure;
669 GClosure *name_acquired_closure;
670 GClosure *name_lost_closure;
671 } OwnNameData;
673 static OwnNameData *
674 own_name_data_new (GClosure *bus_acquired_closure,
675 GClosure *name_acquired_closure,
676 GClosure *name_lost_closure)
678 OwnNameData *data;
680 data = g_new0 (OwnNameData, 1);
682 if (bus_acquired_closure != NULL)
684 data->bus_acquired_closure = g_closure_ref (bus_acquired_closure);
685 g_closure_sink (bus_acquired_closure);
686 if (G_CLOSURE_NEEDS_MARSHAL (bus_acquired_closure))
687 g_closure_set_marshal (bus_acquired_closure, g_cclosure_marshal_generic);
690 if (name_acquired_closure != NULL)
692 data->name_acquired_closure = g_closure_ref (name_acquired_closure);
693 g_closure_sink (name_acquired_closure);
694 if (G_CLOSURE_NEEDS_MARSHAL (name_acquired_closure))
695 g_closure_set_marshal (name_acquired_closure, g_cclosure_marshal_generic);
698 if (name_lost_closure != NULL)
700 data->name_lost_closure = g_closure_ref (name_lost_closure);
701 g_closure_sink (name_lost_closure);
702 if (G_CLOSURE_NEEDS_MARSHAL (name_lost_closure))
703 g_closure_set_marshal (name_lost_closure, g_cclosure_marshal_generic);
706 return data;
709 static void
710 own_with_closures_on_bus_acquired (GDBusConnection *connection,
711 const gchar *name,
712 gpointer user_data)
714 OwnNameData *data = user_data;
715 GValue params[2] = { G_VALUE_INIT, G_VALUE_INIT };
717 g_value_init (&params[0], G_TYPE_DBUS_CONNECTION);
718 g_value_set_object (&params[0], connection);
720 g_value_init (&params[1], G_TYPE_STRING);
721 g_value_set_string (&params[1], name);
723 g_closure_invoke (data->bus_acquired_closure, NULL, 2, params, NULL);
725 g_value_unset (params + 0);
726 g_value_unset (params + 1);
729 static void
730 own_with_closures_on_name_acquired (GDBusConnection *connection,
731 const gchar *name,
732 gpointer user_data)
734 OwnNameData *data = user_data;
735 GValue params[2] = { G_VALUE_INIT, G_VALUE_INIT };
737 g_value_init (&params[0], G_TYPE_DBUS_CONNECTION);
738 g_value_set_object (&params[0], connection);
740 g_value_init (&params[1], G_TYPE_STRING);
741 g_value_set_string (&params[1], name);
743 g_closure_invoke (data->name_acquired_closure, NULL, 2, params, NULL);
745 g_value_unset (params + 0);
746 g_value_unset (params + 1);
749 static void
750 own_with_closures_on_name_lost (GDBusConnection *connection,
751 const gchar *name,
752 gpointer user_data)
754 OwnNameData *data = user_data;
755 GValue params[2] = { G_VALUE_INIT, G_VALUE_INIT };
757 g_value_init (&params[0], G_TYPE_DBUS_CONNECTION);
758 g_value_set_object (&params[0], connection);
760 g_value_init (&params[1], G_TYPE_STRING);
761 g_value_set_string (&params[1], name);
763 g_closure_invoke (data->name_lost_closure, NULL, 2, params, NULL);
765 g_value_unset (params + 0);
766 g_value_unset (params + 1);
769 static void
770 bus_own_name_free_func (gpointer user_data)
772 OwnNameData *data = user_data;
774 if (data->bus_acquired_closure != NULL)
775 g_closure_unref (data->bus_acquired_closure);
777 if (data->name_acquired_closure != NULL)
778 g_closure_unref (data->name_acquired_closure);
780 if (data->name_lost_closure != NULL)
781 g_closure_unref (data->name_lost_closure);
783 g_free (data);
787 * g_bus_own_name_with_closures: (rename-to g_bus_own_name)
788 * @bus_type: the type of bus to own a name on
789 * @name: the well-known name to own
790 * @flags: a set of flags from the #GBusNameOwnerFlags enumeration
791 * @bus_acquired_closure: (nullable): #GClosure to invoke when connected to
792 * the bus of type @bus_type or %NULL
793 * @name_acquired_closure: (nullable): #GClosure to invoke when @name is
794 * acquired or %NULL
795 * @name_lost_closure: (nullable): #GClosure to invoke when @name is lost or
796 * %NULL
798 * Version of g_bus_own_name() using closures instead of callbacks for
799 * easier binding in other languages.
801 * Returns: an identifier (never 0) that an be used with
802 * g_bus_unown_name() to stop owning the name.
804 * Since: 2.26
806 guint
807 g_bus_own_name_with_closures (GBusType bus_type,
808 const gchar *name,
809 GBusNameOwnerFlags flags,
810 GClosure *bus_acquired_closure,
811 GClosure *name_acquired_closure,
812 GClosure *name_lost_closure)
814 return g_bus_own_name (bus_type,
815 name,
816 flags,
817 bus_acquired_closure != NULL ? own_with_closures_on_bus_acquired : NULL,
818 name_acquired_closure != NULL ? own_with_closures_on_name_acquired : NULL,
819 name_lost_closure != NULL ? own_with_closures_on_name_lost : NULL,
820 own_name_data_new (bus_acquired_closure,
821 name_acquired_closure,
822 name_lost_closure),
823 bus_own_name_free_func);
827 * g_bus_own_name_on_connection_with_closures: (rename-to g_bus_own_name_on_connection)
828 * @connection: a #GDBusConnection
829 * @name: the well-known name to own
830 * @flags: a set of flags from the #GBusNameOwnerFlags enumeration
831 * @name_acquired_closure: (nullable): #GClosure to invoke when @name is
832 * acquired or %NULL
833 * @name_lost_closure: (nullable): #GClosure to invoke when @name is lost
834 * or %NULL
836 * Version of g_bus_own_name_on_connection() using closures instead of
837 * callbacks for easier binding in other languages.
839 * Returns: an identifier (never 0) that an be used with
840 * g_bus_unown_name() to stop owning the name.
842 * Since: 2.26
844 guint
845 g_bus_own_name_on_connection_with_closures (GDBusConnection *connection,
846 const gchar *name,
847 GBusNameOwnerFlags flags,
848 GClosure *name_acquired_closure,
849 GClosure *name_lost_closure)
851 return g_bus_own_name_on_connection (connection,
852 name,
853 flags,
854 name_acquired_closure != NULL ? own_with_closures_on_name_acquired : NULL,
855 name_lost_closure != NULL ? own_with_closures_on_name_lost : NULL,
856 own_name_data_new (NULL,
857 name_acquired_closure,
858 name_lost_closure),
859 bus_own_name_free_func);
863 * g_bus_unown_name:
864 * @owner_id: an identifier obtained from g_bus_own_name()
866 * Stops owning a name.
868 * Since: 2.26
870 void
871 g_bus_unown_name (guint owner_id)
873 Client *client;
875 g_return_if_fail (owner_id > 0);
877 client = NULL;
879 G_LOCK (lock);
880 if (owner_id == 0 || map_id_to_client == NULL ||
881 (client = g_hash_table_lookup (map_id_to_client, GUINT_TO_POINTER (owner_id))) == NULL)
883 g_warning ("Invalid id %d passed to g_bus_unown_name()", owner_id);
884 goto out;
887 client->cancelled = TRUE;
888 g_warn_if_fail (g_hash_table_remove (map_id_to_client, GUINT_TO_POINTER (owner_id)));
890 out:
891 G_UNLOCK (lock);
893 /* do callback without holding lock */
894 if (client != NULL)
896 /* Release the name if needed */
897 if (client->needs_release &&
898 client->connection != NULL &&
899 !g_dbus_connection_is_closed (client->connection))
901 GVariant *result;
902 GError *error;
903 guint32 release_name_reply;
905 /* TODO: it kinda sucks having to do a sync call to release the name - but if
906 * we don't, then a subsequent grab of the name will make the bus daemon return
907 * IN_QUEUE which will trigger name_lost().
909 * I believe this is a bug in the bus daemon.
911 error = NULL;
912 result = g_dbus_connection_call_sync (client->connection,
913 "org.freedesktop.DBus", /* bus name */
914 "/org/freedesktop/DBus", /* object path */
915 "org.freedesktop.DBus", /* interface name */
916 "ReleaseName", /* method name */
917 g_variant_new ("(s)", client->name),
918 G_VARIANT_TYPE ("(u)"),
919 G_DBUS_CALL_FLAGS_NONE,
921 NULL,
922 &error);
923 if (result == NULL)
925 g_warning ("Error releasing name %s: %s", client->name, error->message);
926 g_error_free (error);
928 else
930 g_variant_get (result, "(u)", &release_name_reply);
931 if (release_name_reply != 1 /* DBUS_RELEASE_NAME_REPLY_RELEASED */)
933 g_warning ("Unexpected reply %d when releasing name %s", release_name_reply, client->name);
935 g_variant_unref (result);
939 if (client->disconnected_signal_handler_id > 0)
940 g_signal_handler_disconnect (client->connection, client->disconnected_signal_handler_id);
941 if (client->name_acquired_subscription_id > 0)
942 g_dbus_connection_signal_unsubscribe (client->connection, client->name_acquired_subscription_id);
943 if (client->name_lost_subscription_id > 0)
944 g_dbus_connection_signal_unsubscribe (client->connection, client->name_lost_subscription_id);
945 client->disconnected_signal_handler_id = 0;
946 client->name_acquired_subscription_id = 0;
947 client->name_lost_subscription_id = 0;
948 if (client->connection != NULL)
950 g_object_unref (client->connection);
951 client->connection = NULL;
954 client_unref (client);