diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-06-12 03:50:45 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-06-12 03:50:45 +0000 |
commit | efeb864cb547a2cbf96dc0053a8bdb4d9190b364 (patch) | |
tree | c0b83368f18be983fcc763200c4c24d633244588 /man/sd_bus_service_reconnect.c | |
parent | Releasing progress-linux version 255.5-1~progress7.99u1. (diff) | |
download | systemd-efeb864cb547a2cbf96dc0053a8bdb4d9190b364.tar.xz systemd-efeb864cb547a2cbf96dc0053a8bdb4d9190b364.zip |
Merging upstream version 256.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'man/sd_bus_service_reconnect.c')
-rw-r--r-- | man/sd_bus_service_reconnect.c | 205 |
1 files changed, 128 insertions, 77 deletions
diff --git a/man/sd_bus_service_reconnect.c b/man/sd_bus_service_reconnect.c index fdb18c3..fc7c3b1 100644 --- a/man/sd_bus_service_reconnect.c +++ b/man/sd_bus_service_reconnect.c @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: MIT-0 */ -/* Implements a D-Bus service that automatically reconnects when the system bus is restarted. +/* A D-Bus service that automatically reconnects when the system bus is + * restarted. * * Compile with 'cc sd_bus_service_reconnect.c $(pkg-config --libs --cflags libsystemd)' * @@ -10,18 +11,18 @@ <?xml version="1.0"?> <!--*-nxml-*--> <!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN" - "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd"> + "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd"> <busconfig> - <policy user="root"> - <allow own="org.freedesktop.ReconnectExample"/> - <allow send_destination="org.freedesktop.ReconnectExample"/> - <allow receive_sender="org.freedesktop.ReconnectExample"/> - </policy> - - <policy context="default"> - <allow send_destination="org.freedesktop.ReconnectExample"/> - <allow receive_sender="org.freedesktop.ReconnectExample"/> - </policy> + <policy user="root"> + <allow own="org.freedesktop.ReconnectExample"/> + <allow send_destination="org.freedesktop.ReconnectExample"/> + <allow receive_sender="org.freedesktop.ReconnectExample"/> + </policy> + + <policy context="default"> + <allow send_destination="org.freedesktop.ReconnectExample"/> + <allow receive_sender="org.freedesktop.ReconnectExample"/> + </policy> </busconfig> * @@ -31,7 +32,7 @@ * /org/freedesktop/ReconnectExample \ * org.freedesktop.ReconnectExample \ * Example - * s "example" + * s "example" */ #include <errno.h> @@ -41,13 +42,10 @@ #define _cleanup_(f) __attribute__((cleanup(f))) -#define check(x) ({ \ - int _r = (x); \ - errno = _r < 0 ? -_r : 0; \ - printf(#x ": %m\n"); \ - if (_r < 0) \ - return EXIT_FAILURE; \ - }) +static int log_error(int r, const char *str) { + fprintf(stderr, "%s failed: %s\n", str, strerror(-r)); + return r; +} typedef struct object { const char *example; @@ -89,12 +87,24 @@ static const sd_bus_vtable vtable[] = { static int setup(object *o); static int on_disconnect(sd_bus_message *message, void *userdata, sd_bus_error *ret_error) { - check(setup((object *)userdata)); - return 0; + int r; + + r = setup((object *)userdata); + if (r < 0) { + object *o = userdata; + r = sd_event_exit(*o->event, r); + if (r < 0) + return log_error(r, "sd_event_exit()"); + } + + return 1; } -/* Ensure the event loop exits with a clear error if acquiring the well-known service name fails */ +/* 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) { + int r; + if (!sd_bus_message_is_method_error(m, NULL)) return 1; @@ -103,27 +113,34 @@ static int request_name_callback(sd_bus_message *m, void *userdata, sd_bus_error 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); + fprintf(stderr, "Failed to request name: %s\n", error->message); object *o = userdata; - check(sd_event_exit(*o->event, -sd_bus_error_get_errno(error))); + r = sd_event_exit(*o->event, -sd_bus_error_get_errno(error)); + if (r < 0) + return log_error(r, "sd_event_exit()"); 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. + int r; + + /* If we are reconnecting, then the bus object needs to be closed, detached + * from the event loop and recreated. * https://www.freedesktop.org/software/systemd/man/sd_bus_detach_event.html * https://www.freedesktop.org/software/systemd/man/sd_bus_close_unref.html */ if (*o->bus) { - check(sd_bus_detach_event(*o->bus)); + r = sd_bus_detach_event(*o->bus); + if (r < 0) + return log_error(r, "sd_bus_detach_event()"); *o->bus = sd_bus_close_unref(*o->bus); } - /* Set up a new bus object for the system bus, configure it to wait for D-Bus to be available - * instead of failing if it is not, and start it. All the following operations are asyncronous - * and will not block waiting for D-Bus to be available. + /* Set up a new bus object for the system bus, configure it to wait for D-Bus + * to be available instead of failing if it is not, and start it. All the + * following operations are asynchronous and will not block waiting for D-Bus + * to be available. * https://www.freedesktop.org/software/systemd/man/sd_bus_new.html * https://www.freedesktop.org/software/systemd/man/sd_bus_set_address.html * https://www.freedesktop.org/software/systemd/man/sd_bus_set_bus_client.html @@ -132,62 +149,82 @@ static int setup(object *o) { * https://www.freedesktop.org/software/systemd/man/sd_bus_set_connected_signal.html * https://www.freedesktop.org/software/systemd/man/sd_bus_start.html */ - check(sd_bus_new(o->bus)); - check(sd_bus_set_address(*o->bus, "unix:path=/run/dbus/system_bus_socket")); - 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_start(*o->bus)); + r = sd_bus_new(o->bus); + if (r < 0) + return log_error(r, "sd_bus_new()"); + r = sd_bus_set_address(*o->bus, "unix:path=/run/dbus/system_bus_socket"); + if (r < 0) + return log_error(r, "sd_bus_set_address()"); + r = sd_bus_set_bus_client(*o->bus, 1); + if (r < 0) + return log_error(r, "sd_bus_set_bus_client()"); + r = sd_bus_negotiate_creds(*o->bus, 1, SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_EFFECTIVE_CAPS); + if (r < 0) + return log_error(r, "sd_bus_negotiate_creds()"); + r = sd_bus_set_watch_bind(*o->bus, 1); + if (r < 0) + return log_error(r, "sd_bus_set_watch_bind()"); + r = sd_bus_start(*o->bus); + if (r < 0) + return log_error(r, "sd_bus_start()"); /* Publish an interface on the bus, specifying our well-known object access * path and public interface name. * https://www.freedesktop.org/software/systemd/man/sd_bus_add_object.html * https://dbus.freedesktop.org/doc/dbus-tutorial.html */ - check(sd_bus_add_object_vtable(*o->bus, - NULL, - "/org/freedesktop/ReconnectExample", - "org.freedesktop.ReconnectExample", - vtable, - 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. The callback will check whether the error is - * expected or not, in case it fails. + r = sd_bus_add_object_vtable(*o->bus, + NULL, + "/org/freedesktop/ReconnectExample", + "org.freedesktop.ReconnectExample", + vtable, + o); + if (r < 0) + return log_error(r, "sd_bus_add_object_vtable()"); + /* 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. 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, - 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. + r = sd_bus_request_name_async(*o->bus, + NULL, + "org.freedesktop.ReconnectExample", + 0, + request_name_callback, + o); + if (r < 0) + return log_error(r, "sd_bus_request_name_async()"); + /* 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. * https://www.freedesktop.org/software/systemd/man/sd_bus_match_signal_async.html */ - check(sd_bus_match_signal_async(*o->bus, - NULL, - "org.freedesktop.DBus.Local", - NULL, - "org.freedesktop.DBus.Local", - "Disconnected", - on_disconnect, - NULL, - o)); - /* Attach the bus object to the event loop so that calls and signals are processed. + r = sd_bus_match_signal_async(*o->bus, + NULL, + "org.freedesktop.DBus.Local", + NULL, + "org.freedesktop.DBus.Local", + "Disconnected", + on_disconnect, + NULL, + o); + if (r < 0) + return log_error(r, "sd_bus_match_signal_async()"); + /* Attach the bus object to the event loop so that calls and signals are + * processed. * https://www.freedesktop.org/software/systemd/man/sd_bus_attach_event.html */ - check(sd_bus_attach_event(*o->bus, *o->event, 0)); + r = sd_bus_attach_event(*o->bus, *o->event, 0); + if (r < 0) + return log_error(r, "sd_bus_attach_event()"); return 0; } int main(int argc, char **argv) { /* The bus should be relinquished before the program terminates. The cleanup - * attribute allows us to do it nicely and cleanly whenever we exit the - * block. + * attribute allows us to do it nicely and cleanly whenever we exit the block. */ _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; _cleanup_(sd_event_unrefp) sd_event *event = NULL; @@ -196,28 +233,42 @@ int main(int argc, char **argv) { .bus = &bus, .event = &event, }; + int r; /* Create an event loop data structure, with default parameters. * https://www.freedesktop.org/software/systemd/man/sd_event_default.html */ - check(sd_event_default(&event)); + r = sd_event_default(&event); + if (r < 0) + return log_error(r, "sd_event_default()"); - /* By default the event loop will terminate when all sources have disappeared, so - * we have to keep it 'occupied'. Register signal handling to do so. + /* By default the event loop will terminate when all sources have disappeared, + * so we have to keep it 'occupied'. Register signal handling to do so. * https://www.freedesktop.org/software/systemd/man/sd_event_add_signal.html */ - check(sd_event_add_signal(event, NULL, SIGINT|SD_EVENT_SIGNAL_PROCMASK, NULL, NULL)); - check(sd_event_add_signal(event, NULL, SIGTERM|SD_EVENT_SIGNAL_PROCMASK, NULL, NULL)); + r = sd_event_add_signal(event, NULL, SIGINT|SD_EVENT_SIGNAL_PROCMASK, NULL, NULL); + if (r < 0) + return log_error(r, "sd_event_add_signal(SIGINT)"); + + r = sd_event_add_signal(event, NULL, SIGTERM|SD_EVENT_SIGNAL_PROCMASK, NULL, NULL); + if (r < 0) + return log_error(r, "sd_event_add_signal(SIGTERM)"); - check(setup(&o)); + r = setup(&o); + if (r < 0) + return EXIT_FAILURE; /* Enter the main loop, it will exit only on sigint/sigterm. * https://www.freedesktop.org/software/systemd/man/sd_event_loop.html */ - check(sd_event_loop(event)); + r = sd_event_loop(event); + if (r < 0) + return log_error(r, "sd_event_loop()"); /* https://www.freedesktop.org/software/systemd/man/sd_bus_release_name.html */ - check(sd_bus_release_name(bus, "org.freedesktop.ReconnectExample")); + r = sd_bus_release_name(bus, "org.freedesktop.ReconnectExample"); + if (r < 0) + return log_error(r, "sd_bus_release_name()"); return 0; } |