From fa17b4e8d93c715793e35242829b33fef54bddea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Wed, 6 Jun 2018 11:07:02 +0200 Subject: [PATCH] bus: optionally call a callbacks for cleanup This adds a function sd_bus_slot_set_destroy_callback() to set a function which can free userdata or perform other cleanups. sd_bus_slot_get_destory_callback() queries the callback, and is included for completeness. Without something like this, for floating asynchronous callbacks, which might be called or not, depending on the sequence of events, it's hard to perform resource cleanup. The alternative would be to always perform the cleanup from the caller too, but that requires more coordination and keeping of some shared state. It's nicer to keep the cleanup contained between the callback and the function that requests the callback. --- man/rules/meson.build | 4 + man/sd_bus_slot_set_destroy_callback.xml | 105 +++++++++++++++++++++++ man/sd_bus_slot_set_floating.xml | 1 + src/libsystemd/libsystemd.sym | 2 + src/libsystemd/sd-bus/bus-internal.h | 1 + src/libsystemd/sd-bus/bus-slot.c | 20 +++++ src/systemd/sd-bus.h | 3 + 7 files changed, 136 insertions(+) create mode 100644 man/sd_bus_slot_set_destroy_callback.xml diff --git a/man/rules/meson.build b/man/rules/meson.build index e1e2c5e60d..efbd940fe0 100644 --- a/man/rules/meson.build +++ b/man/rules/meson.build @@ -231,6 +231,10 @@ manpages = [ ['sd_bus_set_connected_signal', '3', ['sd_bus_get_connected_signal'], ''], ['sd_bus_set_sender', '3', ['sd_bus_get_sender'], ''], ['sd_bus_set_watch_bind', '3', ['sd_bus_get_watch_bind'], ''], + ['sd_bus_slot_set_destroy_callback', + '3', + ['sd_bus_slot_get_destroy_callback'], + ''], ['sd_bus_slot_set_floating', '3', ['sd_bus_slot_get_floating'], ''], ['sd_bus_track_add_name', '3', diff --git a/man/sd_bus_slot_set_destroy_callback.xml b/man/sd_bus_slot_set_destroy_callback.xml new file mode 100644 index 0000000000..6334444f9a --- /dev/null +++ b/man/sd_bus_slot_set_destroy_callback.xml @@ -0,0 +1,105 @@ + + + + + + + + + sd_bus_slot_set_destroy_callback + systemd + + + + sd_bus_slot_set_destroy_callback + 3 + + + + sd_bus_slot_set_destroy_callback + sd_bus_slot_get_destroy_callback + + Define the callback function for resource cleanup. + + + + + #include <systemd/sd-bus.h> + + + typedef int (*sd_bus_destroy_t) + void *userdata + + + + int sd_bus_slot_set_destroy_callback + sd_bus_slot *slot + sd_bus_destroy_t callback + + + + int sd_bus_slot_get_destroy_callback + sd_bus_slot *slot + sd_bus_destroy_t *callback + + + + + + Description + + sd_bus_slot_set_destroy_callback() sets + callback as the callback function to be called right before the bus slot + object slot is deallocated. The userdata pointer + from the slot object will be passed as the userdata parameter. This + pointer can be set specified as an argument to the constuctor functions, see + sd_bus_add_match3, + or directly, see + sd_bus_set_userdata3. + This callback function is called even if userdata is + NULL. + + sd_bus_slot_get_destroy_callback() returns the current callback + for slot in the callback parameter. + + + + Return Value + + On success, sd_bus_slot_set_destroy_callback() returns 0 or a + positive integer. On failure, it returns a negative errno-style error code. + + sd_bus_slot_get_destroy_callback() returns 1 if the destroy callback + function is set, 0 if not. On failure, it returns a negative errno-style error code. + + + + Errors + + Returned errors may indicate the following problems: + + + + -EINVAL + + The slot parameter is NULL. + + + + + + + + + See Also + + + systemd1, + sd-bus3, + sd_bus_slot_set_floating3 + + + + diff --git a/man/sd_bus_slot_set_floating.xml b/man/sd_bus_slot_set_floating.xml index cae1f5353c..650b56f8c2 100644 --- a/man/sd_bus_slot_set_floating.xml +++ b/man/sd_bus_slot_set_floating.xml @@ -110,6 +110,7 @@ systemd1, sd-bus3, + sd_bus_slot_set_destroy_callback3, sd_bus_add_match3 diff --git a/src/libsystemd/libsystemd.sym b/src/libsystemd/libsystemd.sym index 1bc70cc1f2..dc9c2d241a 100644 --- a/src/libsystemd/libsystemd.sym +++ b/src/libsystemd/libsystemd.sym @@ -563,6 +563,8 @@ global: sd_bus_open_system_with_description; sd_bus_slot_get_floating; sd_bus_slot_set_floating; + sd_bus_slot_get_destroy_callback; + sd_bus_slot_set_destroy_callback; sd_event_add_inotify; sd_event_source_get_inotify_mask; } LIBSYSTEMD_238; diff --git a/src/libsystemd/sd-bus/bus-internal.h b/src/libsystemd/sd-bus/bus-internal.h index 4bce0a7e32..05321d4e79 100644 --- a/src/libsystemd/sd-bus/bus-internal.h +++ b/src/libsystemd/sd-bus/bus-internal.h @@ -127,6 +127,7 @@ struct sd_bus_slot { unsigned n_ref; sd_bus *bus; void *userdata; + sd_bus_destroy_t destroy_callback; BusSlotType type:5; /* Slots can be "floating" or not. If they are not floating (the usual case) then they reference the bus object diff --git a/src/libsystemd/sd-bus/bus-slot.c b/src/libsystemd/sd-bus/bus-slot.c index 34cfdd29e9..db9af9a97e 100644 --- a/src/libsystemd/sd-bus/bus-slot.c +++ b/src/libsystemd/sd-bus/bus-slot.c @@ -203,6 +203,10 @@ _public_ sd_bus_slot* sd_bus_slot_unref(sd_bus_slot *slot) { } bus_slot_disconnect(slot); + + if (slot->destroy_callback) + slot->destroy_callback(slot->userdata); + free(slot->description); return mfree(slot); } @@ -230,6 +234,22 @@ _public_ void *sd_bus_slot_set_userdata(sd_bus_slot *slot, void *userdata) { return ret; } +_public_ int sd_bus_slot_set_destroy_callback(sd_bus_slot *slot, sd_bus_destroy_t callback) { + assert_return(slot, -EINVAL); + + slot->destroy_callback = callback; + return 0; +} + +_public_ int sd_bus_slot_get_destroy_callback(sd_bus_slot *slot, sd_bus_destroy_t *callback) { + assert_return(slot, -EINVAL); + + if (callback) + *callback = slot->destroy_callback; + + return !!slot->destroy_callback; +} + _public_ sd_bus_message *sd_bus_slot_get_current_message(sd_bus_slot *slot) { assert_return(slot, NULL); assert_return(slot->type >= 0, NULL); diff --git a/src/systemd/sd-bus.h b/src/systemd/sd-bus.h index 740e40439e..b2394763c1 100644 --- a/src/systemd/sd-bus.h +++ b/src/systemd/sd-bus.h @@ -111,6 +111,7 @@ typedef int (*sd_bus_property_set_t) (sd_bus *bus, const char *path, const char typedef int (*sd_bus_object_find_t) (sd_bus *bus, const char *path, const char *interface, void *userdata, void **ret_found, sd_bus_error *ret_error); typedef int (*sd_bus_node_enumerator_t) (sd_bus *bus, const char *prefix, void *userdata, char ***ret_nodes, sd_bus_error *ret_error); typedef int (*sd_bus_track_handler_t) (sd_bus_track *track, void *userdata); +typedef void (*sd_bus_destroy_t)(void *userdata); #include "sd-bus-protocol.h" #include "sd-bus-vtable.h" @@ -230,6 +231,8 @@ int sd_bus_slot_set_description(sd_bus_slot *slot, const char *description); int sd_bus_slot_get_description(sd_bus_slot *slot, const char **description); int sd_bus_slot_get_floating(sd_bus_slot *slot); int sd_bus_slot_set_floating(sd_bus_slot *slot, int b); +int sd_bus_slot_set_destroy_callback(sd_bus_slot *s, sd_bus_destroy_t callback); +int sd_bus_slot_get_destroy_callback(sd_bus_slot *s, sd_bus_destroy_t *callback); sd_bus_message* sd_bus_slot_get_current_message(sd_bus_slot *slot); sd_bus_message_handler_t sd_bus_slot_get_current_handler(sd_bus_slot *bus);