diff --git a/src/libsystemd/libsystemd.sym b/src/libsystemd/libsystemd.sym index 529f401a84..6f2075a33a 100644 --- a/src/libsystemd/libsystemd.sym +++ b/src/libsystemd/libsystemd.sym @@ -561,4 +561,6 @@ global: sd_bus_open_with_description; sd_bus_open_user_with_description; sd_bus_open_system_with_description; + sd_bus_slot_get_floating; + sd_bus_slot_set_floating; } LIBSYSTEMD_238; diff --git a/src/libsystemd/sd-bus/bus-internal.h b/src/libsystemd/sd-bus/bus-internal.h index e84ea0f6bf..4bce0a7e32 100644 --- a/src/libsystemd/sd-bus/bus-internal.h +++ b/src/libsystemd/sd-bus/bus-internal.h @@ -128,7 +128,15 @@ struct sd_bus_slot { sd_bus *bus; void *userdata; BusSlotType type:5; + + /* Slots can be "floating" or not. If they are not floating (the usual case) then they reference the bus object + * they are associated with. This means the bus object stays allocated at least as long as there is a slot + * around associated with it. If it is floating, then the slot's lifecycle is bound to the lifecycle of the + * bus: it will be disconnected from the bus when the bus is destroyed, and it keeping the slot reffed hence + * won't mean the bus stays reffed too. Internally this means the reference direction is reversed: floating + * slots objects are referenced by the bus object, and not vice versa. */ bool floating:1; + bool match_added:1; char *description; diff --git a/src/libsystemd/sd-bus/bus-slot.c b/src/libsystemd/sd-bus/bus-slot.c index 3745426c5c..3e592e3a2f 100644 --- a/src/libsystemd/sd-bus/bus-slot.c +++ b/src/libsystemd/sd-bus/bus-slot.c @@ -260,6 +260,37 @@ _public_ void* sd_bus_slot_get_current_userdata(sd_bus_slot *slot) { return slot->bus->current_userdata; } +_public_ int sd_bus_slot_get_floating(sd_bus_slot *slot) { + assert_return(slot, -EINVAL); + + return slot->floating; +} + +_public_ int sd_bus_slot_set_floating(sd_bus_slot *slot, int b) { + assert_return(slot, -EINVAL); + + if (slot->floating == !!b) + return 0; + + if (!slot->bus) /* already disconnected slots can't be reconnected */ + return -ESTALE; + + slot->floating = b; + + /* When a slot is "floating" then the bus references the slot. Otherwise the slot references the bus. Hence, + * when we move from one to the other, let's increase one reference and decrease the other. */ + + if (b) { + sd_bus_slot_ref(slot); + sd_bus_unref(slot->bus); + } else { + sd_bus_ref(slot->bus); + sd_bus_slot_unref(slot); + } + + return 1; +} + _public_ int sd_bus_slot_set_description(sd_bus_slot *slot, const char *description) { assert_return(slot, -EINVAL); diff --git a/src/systemd/sd-bus.h b/src/systemd/sd-bus.h index 90b9dd84c2..740e40439e 100644 --- a/src/systemd/sd-bus.h +++ b/src/systemd/sd-bus.h @@ -228,6 +228,8 @@ void *sd_bus_slot_get_userdata(sd_bus_slot *slot); void *sd_bus_slot_set_userdata(sd_bus_slot *slot, void *userdata); 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); 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);