]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - man/sd_bus_service_reconnect.c
man: enchance sd_bus_set_watch_bind() example to handle one more failure
[thirdparty/systemd.git] / man / sd_bus_service_reconnect.c
index 10c776b0355da616d8ea0d8789dd020a66bf9a21..0b75086ef1bc2682d100a54929323581f729cf21 100644 (file)
@@ -5,7 +5,8 @@
  * Compile with 'cc sd_bus_service_reconnect.c $(pkg-config --libs --cflags libsystemd)'
  *
  * To allow the program to take ownership of the name 'org.freedesktop.ReconnectExample',
- * add the following as /etc/dbus-1/system.d/org.freedesktop.ReconnectExample.conf:
+ * add the following as /etc/dbus-1/system.d/org.freedesktop.ReconnectExample.conf
+ * and then reload the broker with 'systemctl reload dbus':
 
 <?xml version="1.0"?> <!--*-nxml-*-->
 <!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
@@ -92,6 +93,23 @@ static int on_disconnect(sd_bus_message *message, void *userdata, sd_bus_error *
   return 0;
 }
 
+/* Ensure the event loop exits with a clear error if acquiring the well-known service name fails */
+static int request_name_callback(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
+  if (!sd_bus_message_is_method_error(m, NULL))
+    return 1;
+
+  const sd_bus_error *error = sd_bus_message_get_error(m);
+
+  if (sd_bus_error_has_names(error, SD_BUS_ERROR_TIMEOUT, SD_BUS_ERROR_NO_REPLY))
+    return 1; /* The bus is not available, try again later */
+
+  printf("Failed to request name: %s\n", error->message);
+  object *o = userdata;
+  check(sd_event_exit(*o->event, -sd_bus_error_get_errno(error)));
+
+  return 1;
+}
+
 static int setup(object *o) {
   /* If we are reconnecting, then the bus object needs to be closed, detached from
    * the event loop and recreated.
@@ -119,7 +137,6 @@ static int setup(object *o) {
   check(sd_bus_set_bus_client(*o->bus, 1));
   check(sd_bus_negotiate_creds(*o->bus, 1, SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_EFFECTIVE_CAPS));
   check(sd_bus_set_watch_bind(*o->bus, 1));
-  check(sd_bus_set_connected_signal(*o->bus, 1));
   check(sd_bus_start(*o->bus));
 
   /* Publish an interface on the bus, specifying our well-known object access
@@ -135,15 +152,16 @@ static int setup(object *o) {
                                  o));
   /* By default the service is only assigned an ephemeral name. Also add a well-known
    * one, so that clients know whom to call. This needs to be asynchronous, as
-   * D-Bus might not be yet available.
+   * D-Bus might not be yet available. The callback will check whether the error is
+   * expected or not, in case it fails.
    * https://www.freedesktop.org/software/systemd/man/sd_bus_request_name.html
    */
   check(sd_bus_request_name_async(*o->bus,
                                   NULL,
                                   "org.freedesktop.ReconnectExample",
                                   0,
-                                  NULL,
-                                  NULL));
+                                  request_name_callback,
+                                  o));
   /* When D-Bus is disconnected this callback will be invoked, which will
    * set up the connection again. This needs to be asynchronous, as D-Bus might not
    * yet be available.