diff options
Diffstat (limited to 'src')
33 files changed, 863 insertions, 649 deletions
diff --git a/src/bus-proxyd/bus-proxyd.c b/src/bus-proxyd/bus-proxyd.c index c5f9f002fe..e095d61ffb 100644 --- a/src/bus-proxyd/bus-proxyd.c +++ b/src/bus-proxyd/bus-proxyd.c @@ -40,6 +40,7 @@ #include "bus-internal.h" #include "bus-message.h" #include "bus-util.h" +#include "bus-internal.h" #include "build.h" #include "strv.h" #include "def.h" @@ -551,7 +552,7 @@ static int process_driver(sd_bus *a, sd_bus *b, sd_bus_message *m) { if (r < 0) return synthetic_reply_method_errno(m, r, NULL); - r = sd_bus_add_match(a, match, NULL, NULL); + r = sd_bus_add_match(a, NULL, match, NULL, NULL); if (r < 0) return synthetic_reply_method_errno(m, r, NULL); @@ -564,7 +565,9 @@ static int process_driver(sd_bus *a, sd_bus *b, sd_bus_message *m) { if (r < 0) return synthetic_reply_method_errno(m, r, NULL); - r = sd_bus_remove_match(a, match, NULL, NULL); + r = bus_remove_match_by_string(a, match, NULL, NULL); + if (r == 0) + return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_MATCH_RULE_NOT_FOUND, "Match rule not found")); if (r < 0) return synthetic_reply_method_errno(m, r, NULL); @@ -739,9 +742,10 @@ static int process_driver(sd_bus *a, sd_bus *b, sd_bus_message *m) { r = sd_bus_release_name(a, name); if (r < 0) { if (r == -ESRCH) - synthetic_reply_method_return(m, "u", BUS_NAME_NON_EXISTENT); + return synthetic_reply_method_return(m, "u", BUS_NAME_NON_EXISTENT); if (r == -EADDRINUSE) - synthetic_reply_method_return(m, "u", BUS_NAME_NOT_OWNER); + return synthetic_reply_method_return(m, "u", BUS_NAME_NOT_OWNER); + return synthetic_reply_method_errno(m, r, NULL); } @@ -1177,7 +1181,7 @@ int main(int argc, char *argv[]) { goto finish; } - r = sd_bus_add_match(a, match, NULL, NULL); + r = sd_bus_add_match(a, NULL, match, NULL, NULL); if (r < 0) { log_error("Failed to add match for NameLost: %s", strerror(-r)); goto finish; @@ -1198,7 +1202,7 @@ int main(int argc, char *argv[]) { goto finish; } - r = sd_bus_add_match(a, match, NULL, NULL); + r = sd_bus_add_match(a, NULL, match, NULL, NULL); if (r < 0) { log_error("Failed to add match for NameAcquired: %s", strerror(-r)); goto finish; diff --git a/src/core/dbus.c b/src/core/dbus.c index 189d925c9e..fb8e4963e1 100644 --- a/src/core/dbus.c +++ b/src/core/dbus.c @@ -310,7 +310,7 @@ static int find_unit(Manager *m, sd_bus *bus, const char *path, Unit **unit, sd_ sd_bus_message *message; pid_t pid; - message = sd_bus_get_current(bus); + message = sd_bus_get_current_message(bus); if (!message) return 0; @@ -536,58 +536,58 @@ static int bus_setup_api_vtables(Manager *m, sd_bus *bus) { assert(bus); #ifdef HAVE_SELINUX - r = sd_bus_add_filter(bus, selinux_filter, m); + r = sd_bus_add_filter(bus, NULL, selinux_filter, m); if (r < 0) { log_error("Failed to add SELinux access filter: %s", strerror(-r)); return r; } #endif - r = sd_bus_add_object_vtable(bus, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", bus_manager_vtable, m); + r = sd_bus_add_object_vtable(bus, NULL, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", bus_manager_vtable, m); if (r < 0) { log_error("Failed to register Manager vtable: %s", strerror(-r)); return r; } - r = sd_bus_add_fallback_vtable(bus, "/org/freedesktop/systemd1/job", "org.freedesktop.systemd1.Job", bus_job_vtable, bus_job_find, m); + r = sd_bus_add_fallback_vtable(bus, NULL, "/org/freedesktop/systemd1/job", "org.freedesktop.systemd1.Job", bus_job_vtable, bus_job_find, m); if (r < 0) { log_error("Failed to register Job vtable: %s", strerror(-r)); return r; } - r = sd_bus_add_node_enumerator(bus, "/org/freedesktop/systemd1/job", bus_job_enumerate, m); + r = sd_bus_add_node_enumerator(bus, NULL, "/org/freedesktop/systemd1/job", bus_job_enumerate, m); if (r < 0) { log_error("Failed to add job enumerator: %s", strerror(-r)); return r; } - r = sd_bus_add_fallback_vtable(bus, "/org/freedesktop/systemd1/unit", "org.freedesktop.systemd1.Unit", bus_unit_vtable, bus_unit_find, m); + r = sd_bus_add_fallback_vtable(bus, NULL, "/org/freedesktop/systemd1/unit", "org.freedesktop.systemd1.Unit", bus_unit_vtable, bus_unit_find, m); if (r < 0) { log_error("Failed to register Unit vtable: %s", strerror(-r)); return r; } - r = sd_bus_add_node_enumerator(bus, "/org/freedesktop/systemd1/unit", bus_unit_enumerate, m); + r = sd_bus_add_node_enumerator(bus, NULL, "/org/freedesktop/systemd1/unit", bus_unit_enumerate, m); if (r < 0) { log_error("Failed to add job enumerator: %s", strerror(-r)); return r; } for (t = 0; t < _UNIT_TYPE_MAX; t++) { - r = sd_bus_add_fallback_vtable(bus, "/org/freedesktop/systemd1/unit", unit_vtable[t]->bus_interface, unit_vtable[t]->bus_vtable, bus_unit_interface_find, m); + r = sd_bus_add_fallback_vtable(bus, NULL, "/org/freedesktop/systemd1/unit", unit_vtable[t]->bus_interface, unit_vtable[t]->bus_vtable, bus_unit_interface_find, m); if (r < 0) { log_error("Failed to register type specific vtable for %s: %s", unit_vtable[t]->bus_interface, strerror(-r)); return r; } if (unit_vtable[t]->cgroup_context_offset > 0) { - r = sd_bus_add_fallback_vtable(bus, "/org/freedesktop/systemd1/unit", unit_vtable[t]->bus_interface, bus_unit_cgroup_vtable, bus_unit_cgroup_find, m); + r = sd_bus_add_fallback_vtable(bus, NULL, "/org/freedesktop/systemd1/unit", unit_vtable[t]->bus_interface, bus_unit_cgroup_vtable, bus_unit_cgroup_find, m); if (r < 0) { log_error("Failed to register control group unit vtable for %s: %s", unit_vtable[t]->bus_interface, strerror(-r)); return r; } - r = sd_bus_add_fallback_vtable(bus, "/org/freedesktop/systemd1/unit", unit_vtable[t]->bus_interface, bus_cgroup_vtable, bus_cgroup_context_find, m); + r = sd_bus_add_fallback_vtable(bus, NULL, "/org/freedesktop/systemd1/unit", unit_vtable[t]->bus_interface, bus_cgroup_vtable, bus_cgroup_context_find, m); if (r < 0) { log_error("Failed to register control group vtable for %s: %s", unit_vtable[t]->bus_interface, strerror(-r)); return r; @@ -595,7 +595,7 @@ static int bus_setup_api_vtables(Manager *m, sd_bus *bus) { } if (unit_vtable[t]->exec_context_offset > 0) { - r = sd_bus_add_fallback_vtable(bus, "/org/freedesktop/systemd1/unit", unit_vtable[t]->bus_interface, bus_exec_vtable, bus_exec_context_find, m); + r = sd_bus_add_fallback_vtable(bus, NULL, "/org/freedesktop/systemd1/unit", unit_vtable[t]->bus_interface, bus_exec_vtable, bus_exec_context_find, m); if (r < 0) { log_error("Failed to register execute vtable for %s: %s", unit_vtable[t]->bus_interface, strerror(-r)); return r; @@ -603,7 +603,7 @@ static int bus_setup_api_vtables(Manager *m, sd_bus *bus) { } if (unit_vtable[t]->kill_context_offset > 0) { - r = sd_bus_add_fallback_vtable(bus, "/org/freedesktop/systemd1/unit", unit_vtable[t]->bus_interface, bus_kill_vtable, bus_kill_context_find, m); + r = sd_bus_add_fallback_vtable(bus, NULL, "/org/freedesktop/systemd1/unit", unit_vtable[t]->bus_interface, bus_kill_vtable, bus_kill_context_find, m); if (r < 0) { log_error("Failed to register kill vtable for %s: %s", unit_vtable[t]->bus_interface, strerror(-r)); return r; @@ -622,6 +622,7 @@ static int bus_setup_disconnected_match(Manager *m, sd_bus *bus) { r = sd_bus_add_match( bus, + NULL, "sender='org.freedesktop.DBus.Local'," "type='signal'," "path='/org/freedesktop/DBus/Local'," @@ -710,6 +711,7 @@ static int bus_on_connection(sd_event_source *s, int fd, uint32_t revents, void r = sd_bus_add_match( bus, + NULL, "type='signal'," "interface='org.freedesktop.systemd1.Agent'," "member='Released'," @@ -780,6 +782,7 @@ static int bus_setup_api(Manager *m, sd_bus *bus) { r = sd_bus_add_match( bus, + NULL, "type='signal'," "sender='org.freedesktop.DBus'," "path='/org/freedesktop/DBus'," @@ -791,6 +794,7 @@ static int bus_setup_api(Manager *m, sd_bus *bus) { r = sd_bus_add_match( bus, + NULL, "type='signal'," "sender='org.freedesktop.DBus'," "path='/org/freedesktop/DBus'," @@ -874,6 +878,7 @@ static int bus_setup_system(Manager *m, sd_bus *bus) { * the system bus */ r = sd_bus_add_match( bus, + NULL, "type='signal'," "interface='org.freedesktop.systemd1.Agent'," "member='Released'," diff --git a/src/hostname/hostnamed.c b/src/hostname/hostnamed.c index 2be6dcde78..48cbbdb04a 100644 --- a/src/hostname/hostnamed.c +++ b/src/hostname/hostnamed.c @@ -591,7 +591,7 @@ static int connect_bus(Context *c, sd_event *event, sd_bus **_bus) { return r; } - r = sd_bus_add_object_vtable(bus, "/org/freedesktop/hostname1", "org.freedesktop.hostname1", hostname_vtable, c); + r = sd_bus_add_object_vtable(bus, NULL, "/org/freedesktop/hostname1", "org.freedesktop.hostname1", hostname_vtable, c); if (r < 0) { log_error("Failed to register object: %s", strerror(-r)); return r; diff --git a/src/libsystemd/libsystemd.sym.m4 b/src/libsystemd/libsystemd.sym.m4 index 14d9dcf9e9..7545ae4dc1 100644 --- a/src/libsystemd/libsystemd.sym.m4 +++ b/src/libsystemd/libsystemd.sym.m4 @@ -173,7 +173,6 @@ m4_ifdef(`ENABLE_KDBUS', sd_bus_send_to; sd_bus_call; sd_bus_call_async; - sd_bus_call_async_cancel; sd_bus_get_fd; sd_bus_get_events; sd_bus_get_timeout; @@ -181,27 +180,26 @@ m4_ifdef(`ENABLE_KDBUS', sd_bus_process_priority; sd_bus_wait; sd_bus_flush; - sd_bus_get_current; + sd_bus_get_current_message; + sd_bus_get_current_slot; sd_bus_get_tid; sd_bus_attach_event; sd_bus_detach_event; sd_bus_get_event; sd_bus_add_filter; - sd_bus_remove_filter; sd_bus_add_match; - sd_bus_remove_match; sd_bus_add_object; - sd_bus_remove_object; sd_bus_add_fallback; - sd_bus_remove_fallback; sd_bus_add_object_vtable; - sd_bus_remove_object_vtable; sd_bus_add_fallback_vtable; - sd_bus_remove_fallback_vtable; sd_bus_add_node_enumerator; - sd_bus_remove_node_enumerator; sd_bus_add_object_manager; - sd_bus_remove_object_manager; + sd_bus_slot_ref; + sd_bus_slot_unref; + sd_bus_slot_get_bus; + sd_bus_slot_get_userdata; + sd_bus_slot_set_userdata; + sd_bus_slot_get_current_message; sd_bus_message_new_signal; sd_bus_message_new_method_call; sd_bus_message_new_method_return; diff --git a/src/libsystemd/sd-bus/bus-control.h b/src/libsystemd/sd-bus/bus-control.h index 420e091b2e..aa290edac7 100644 --- a/src/libsystemd/sd-bus/bus-control.h +++ b/src/libsystemd/sd-bus/bus-control.h @@ -22,6 +22,7 @@ ***/ #include "sd-bus.h" +#include "bus-match.h" int bus_add_match_internal(sd_bus *bus, const char *match, struct bus_match_component *components, unsigned n_components, uint64_t cookie); int bus_remove_match_internal(sd_bus *bus, const char *match, uint64_t cookie); diff --git a/src/libsystemd/sd-bus/bus-internal.h b/src/libsystemd/sd-bus/bus-internal.h index 3dceb8a5da..042d352261 100644 --- a/src/libsystemd/sd-bus/bus-internal.h +++ b/src/libsystemd/sd-bus/bus-internal.h @@ -40,7 +40,6 @@ struct reply_callback { sd_bus_message_handler_t callback; - void *userdata; usec_t timeout; uint64_t cookie; unsigned prioq_idx; @@ -48,13 +47,23 @@ struct reply_callback { struct filter_callback { sd_bus_message_handler_t callback; - void *userdata; unsigned last_iteration; LIST_FIELDS(struct filter_callback, callbacks); }; +struct match_callback { + sd_bus_message_handler_t callback; + + uint64_t cookie; + unsigned last_iteration; + + char *match_string; + + struct bus_match_node *match_node; +}; + struct node { char *path; struct node *parent; @@ -64,8 +73,7 @@ struct node { LIST_HEAD(struct node_callback, callbacks); LIST_HEAD(struct node_vtable, vtables); LIST_HEAD(struct node_enumerator, enumerators); - - bool object_manager; + LIST_HEAD(struct node_object_manager, object_managers); }; struct node_callback { @@ -73,7 +81,6 @@ struct node_callback { bool is_fallback; sd_bus_message_handler_t callback; - void *userdata; unsigned last_iteration; @@ -84,20 +91,24 @@ struct node_enumerator { struct node *node; sd_bus_node_enumerator_t callback; - void *userdata; unsigned last_iteration; LIST_FIELDS(struct node_enumerator, enumerators); }; +struct node_object_manager { + struct node *node; + + LIST_FIELDS(struct node_object_manager, object_managers); +}; + struct node_vtable { struct node *node; char *interface; bool is_fallback; const sd_bus_vtable *vtable; - void *userdata; sd_bus_object_find_t find; unsigned last_iteration; @@ -114,6 +125,37 @@ struct vtable_member { const sd_bus_vtable *vtable; }; +typedef enum BusSlotType { + _BUS_SLOT_DISCONNECTED, + BUS_REPLY_CALLBACK, + BUS_FILTER_CALLBACK, + BUS_MATCH_CALLBACK, + BUS_NODE_CALLBACK, + BUS_NODE_ENUMERATOR, + BUS_NODE_VTABLE, + BUS_NODE_OBJECT_MANAGER, +} BusSlotType; + +struct sd_bus_slot { + unsigned n_ref; + sd_bus *bus; + void *userdata; + BusSlotType type; + bool floating; + + LIST_FIELDS(sd_bus_slot, slots); + + union { + struct reply_callback reply_callback; + struct filter_callback filter_callback; + struct match_callback match_callback; + struct node_callback node_callback; + struct node_enumerator node_enumerator; + struct node_object_manager node_object_manager; + struct node_vtable node_vtable; + }; +}; + enum bus_state { BUS_UNSET, BUS_OPENING, @@ -231,7 +273,6 @@ struct sd_bus { char *exec_path; char **exec_argv; - uint64_t hello_cookie; unsigned iteration_counter; void *kdbus_buffer; @@ -260,7 +301,8 @@ struct sd_bus { sd_event *event; int event_priority; - sd_bus_message *current; + sd_bus_message *current_message; + sd_bus_slot *current_slot; sd_bus **default_bus_ptr; pid_t tid; @@ -276,6 +318,8 @@ struct sd_bus { unsigned bloom_n_hash; sd_bus_track *track_queue; + + LIST_HEAD(sd_bus_slot, slots); }; #define BUS_DEFAULT_TIMEOUT ((usec_t) (25 * USEC_PER_SEC)) @@ -340,3 +384,5 @@ int bus_set_address_system(sd_bus *bus); int bus_set_address_user(sd_bus *bus); int bus_set_address_system_remote(sd_bus *b, const char *host); int bus_set_address_system_container(sd_bus *b, const char *machine); + +int bus_remove_match_by_string(sd_bus *bus, const char *match, sd_bus_message_handler_t callback, void *userdata); diff --git a/src/libsystemd/sd-bus/bus-match.c b/src/libsystemd/sd-bus/bus-match.c index c54ca8d71d..b868159b5c 100644 --- a/src/libsystemd/sd-bus/bus-match.c +++ b/src/libsystemd/sd-bus/bus-match.c @@ -116,6 +116,9 @@ static void bus_match_node_free(struct bus_match_node *node) { static bool bus_match_node_maybe_free(struct bus_match_node *node) { assert(node); + if (node->type == BUS_MATCH_ROOT) + return false; + if (node->child) return false; @@ -275,10 +278,10 @@ int bus_match_run( case BUS_MATCH_LEAF: if (bus) { - if (node->leaf.last_iteration == bus->iteration_counter) + if (node->leaf.callback->last_iteration == bus->iteration_counter) return 0; - node->leaf.last_iteration = bus->iteration_counter; + node->leaf.callback->last_iteration = bus->iteration_counter; } r = sd_bus_message_rewind(m, true); @@ -287,9 +290,17 @@ int bus_match_run( /* Run the callback. And then invoke siblings. */ if (node->leaf.callback) { + sd_bus_slot *slot; + _cleanup_bus_error_free_ sd_bus_error error_buffer = SD_BUS_ERROR_NULL; - r = node->leaf.callback(bus, m, node->leaf.userdata, &error_buffer); + slot = container_of(node->leaf.callback, sd_bus_slot, match_callback); + if (bus) + bus->current_slot = slot; + r = node->leaf.callback->callback(bus, m, slot->userdata, &error_buffer); + if (bus) + bus->current_slot = NULL; + r = bus_maybe_reply_error(m, r, &error_buffer); if (r != 0) return r; @@ -535,16 +546,13 @@ static int bus_match_find_compare_value( static int bus_match_add_leaf( struct bus_match_node *where, - sd_bus_message_handler_t callback, - void *userdata, - uint64_t cookie, - struct bus_match_node **ret) { + struct match_callback *callback) { struct bus_match_node *n; assert(where); assert(where->type == BUS_MATCH_ROOT || where->type == BUS_MATCH_VALUE); - assert(ret); + assert(callback); n = new0(struct bus_match_node, 1); if (!n) @@ -555,13 +563,12 @@ static int bus_match_add_leaf( n->next = where->child; if (n->next) n->next->prev = n; + n->leaf.callback = callback; - n->leaf.userdata = userdata; - n->leaf.cookie = cookie; + callback->match_node = n; where->child = n; - *ret = n; return 1; } @@ -578,9 +585,13 @@ static int bus_match_find_leaf( assert(ret); for (c = where->child; c; c = c->next) { + sd_bus_slot *s; + + s = container_of(c->leaf.callback, sd_bus_slot, match_callback); + if (c->type == BUS_MATCH_LEAF && - c->leaf.callback == callback && - c->leaf.userdata == userdata) { + c->leaf.callback->callback == callback && + s->userdata == userdata) { *ret = c; return 1; } @@ -892,16 +903,14 @@ int bus_match_add( struct bus_match_node *root, struct bus_match_component *components, unsigned n_components, - sd_bus_message_handler_t callback, - void *userdata, - uint64_t cookie, - struct bus_match_node **ret) { + struct match_callback *callback) { unsigned i; struct bus_match_node *n; int r; assert(root); + assert(callback); n = root; for (i = 0; i < n_components; i++) { @@ -912,29 +921,56 @@ int bus_match_add( return r; } - r = bus_match_add_leaf(n, callback, userdata, cookie, &n); - if (r < 0) - return r; + return bus_match_add_leaf(n, callback); +} - if (ret) - *ret = n; +int bus_match_remove( + struct bus_match_node *root, + struct match_callback *callback) { - return 0; + struct bus_match_node *node, *pp; + + assert(root); + assert(callback); + + node = callback->match_node; + if (!node) + return 0; + + assert(node->type == BUS_MATCH_LEAF); + + callback->match_node = NULL; + + /* Free the leaf */ + pp = node->parent; + bus_match_node_free(node); + + /* Prune the tree above */ + while (pp) { + node = pp; + pp = node->parent; + + if (!bus_match_node_maybe_free(node)) + break; + } + + return 1; } -int bus_match_remove( +int bus_match_find( struct bus_match_node *root, struct bus_match_component *components, unsigned n_components, sd_bus_message_handler_t callback, void *userdata, - uint64_t *cookie) { + struct match_callback **ret) { - unsigned i; struct bus_match_node *n, **gc; + unsigned i; int r; assert(root); + assert(ret); gc = newa(struct bus_match_node*, n_components); @@ -954,24 +990,8 @@ int bus_match_remove( if (r <= 0) return r; - if (cookie) - *cookie = n->leaf.cookie; - - /* Free the leaf */ - bus_match_node_free(n); - - /* Prune the tree above */ - for (i = n_components; i > 0; i --) { - struct bus_match_node *p = gc[i-1]->parent; - - if (!bus_match_node_maybe_free(gc[i-1])) - break; - - if (!bus_match_node_maybe_free(p)) - break; - } - - return r; + *ret = n->leaf.callback; + return 1; } void bus_match_free(struct bus_match_node *node) { @@ -1065,7 +1085,7 @@ void bus_match_dump(struct bus_match_node *node, unsigned level) { } else if (node->type == BUS_MATCH_ROOT) puts(" root"); else if (node->type == BUS_MATCH_LEAF) - printf(" %p/%p\n", node->leaf.callback, node->leaf.userdata); + printf(" %p/%p\n", node->leaf.callback->callback, container_of(node->leaf.callback, sd_bus_slot, match_callback)->userdata); else putchar('\n'); diff --git a/src/libsystemd/sd-bus/bus-match.h b/src/libsystemd/sd-bus/bus-match.h index 056082b908..af5f65d073 100644 --- a/src/libsystemd/sd-bus/bus-match.h +++ b/src/libsystemd/sd-bus/bus-match.h @@ -58,10 +58,7 @@ struct bus_match_node { uint8_t u8; } value; struct { - sd_bus_message_handler_t callback; - void *userdata; - unsigned last_iteration; - uint64_t cookie; + struct match_callback *callback; } leaf; struct { /* If this is set, then the child is NULL */ @@ -78,8 +75,10 @@ struct bus_match_component { int bus_match_run(sd_bus *bus, struct bus_match_node *root, sd_bus_message *m); -int bus_match_add(struct bus_match_node *root, struct bus_match_component *components, unsigned n_components, sd_bus_message_handler_t callback, void *userdata, uint64_t cookie, struct bus_match_node **ret); -int bus_match_remove(struct bus_match_node *root, struct bus_match_component *components, unsigned n_components, sd_bus_message_handler_t callback, void *userdata, uint64_t *cookie); +int bus_match_add(struct bus_match_node *root, struct bus_match_component *components, unsigned n_components, struct match_callback *callback); +int bus_match_remove(struct bus_match_node *root, struct match_callback *callback); + +int bus_match_find(struct bus_match_node *root, struct bus_match_component *components, unsigned n_components, sd_bus_message_handler_t callback, void *userdata, struct match_callback **ret); void bus_match_free(struct bus_match_node *node); diff --git a/src/libsystemd/sd-bus/bus-objects.c b/src/libsystemd/sd-bus/bus-objects.c index 8b12e89164..f160e2343d 100644 --- a/src/libsystemd/sd-bus/bus-objects.c +++ b/src/libsystemd/sd-bus/bus-objects.c @@ -28,8 +28,9 @@ #include "bus-type.h" #include "bus-signature.h" #include "bus-introspect.h" -#include "bus-objects.h" #include "bus-util.h" +#include "bus-slot.h" +#include "bus-objects.h" static int node_vtable_get_userdata( sd_bus *bus, @@ -38,6 +39,7 @@ static int node_vtable_get_userdata( void **userdata, sd_bus_error *error) { + sd_bus_slot *s; void *u; int r; @@ -45,9 +47,13 @@ static int node_vtable_get_userdata( assert(path); assert(c); - u = c->userdata; + s = container_of(c, sd_bus_slot, node_vtable); + u = s->userdata; if (c->find) { + bus->current_slot = s; r = c->find(bus, path, c->interface, u, &u, error); + bus->current_slot = NULL; + if (r < 0) return r; if (sd_bus_error_is_set(error)) @@ -113,7 +119,10 @@ static int add_enumerated_to_set( if (bus->nodes_modified) return 0; - r = c->callback(bus, prefix, c->userdata, &children, error); + bus->current_slot = container_of(c, sd_bus_slot, node_enumerator); + r = c->callback(bus, prefix, bus->current_slot->userdata, &children, error); + bus->current_slot = NULL; + if (r < 0) return r; if (sd_bus_error_is_set(error)) @@ -257,7 +266,10 @@ static int node_callbacks_run( if (r < 0) return r; - r = c->callback(bus, m, c->userdata, &error_buffer); + bus->current_slot = container_of(c, sd_bus_slot, node_callback); + r = c->callback(bus, m, bus->current_slot->userdata, &error_buffer); + bus->current_slot = NULL; + r = bus_maybe_reply_error(m, r, &error_buffer); if (r != 0) return r; @@ -382,7 +394,11 @@ static int method_callbacks_run( m->enforced_reply_signature = strempty(c->vtable->x.method.result); if (c->vtable->x.method.handler) { + + bus->current_slot = container_of(c->parent, sd_bus_slot, node_vtable); r = c->vtable->x.method.handler(bus, m, u, &error); + bus->current_slot = NULL; + return bus_maybe_reply_error(m, r, &error); } @@ -396,6 +412,7 @@ static int method_callbacks_run( static int invoke_property_get( sd_bus *bus, + sd_bus_slot *slot, const sd_bus_vtable *v, const char *path, const char *interface, @@ -408,6 +425,7 @@ static int invoke_property_get( int r; assert(bus); + assert(slot); assert(v); assert(path); assert(interface); @@ -415,7 +433,11 @@ static int invoke_property_get( assert(reply); if (v->x.property.get) { + + bus->current_slot = slot; r = v->x.property.get(bus, path, interface, property, reply, userdata, error); + bus->current_slot = NULL; + if (r < 0) return r; if (sd_bus_error_is_set(error)) @@ -453,6 +475,7 @@ static int invoke_property_get( static int invoke_property_set( sd_bus *bus, + sd_bus_slot *slot, const sd_bus_vtable *v, const char *path, const char *interface, @@ -464,6 +487,7 @@ static int invoke_property_set( int r; assert(bus); + assert(slot); assert(v); assert(path); assert(interface); @@ -471,7 +495,11 @@ static int invoke_property_set( assert(value); if (v->x.property.set) { + + bus->current_slot = slot; r = v->x.property.set(bus, path, interface, property, value, userdata, error); + bus->current_slot = NULL; + if (r < 0) return r; if (sd_bus_error_is_set(error)) @@ -527,6 +555,7 @@ static int property_get_set_callbacks_run( _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_bus_message_unref_ sd_bus_message *reply = NULL; + sd_bus_slot *slot; void *u = NULL; int r; @@ -544,6 +573,8 @@ static int property_get_set_callbacks_run( if (bus->nodes_modified) return 0; + slot = container_of(c->parent, sd_bus_slot, node_vtable); + *found_object = true; r = sd_bus_message_new_method_return(m, &reply); @@ -567,7 +598,7 @@ static int property_get_set_callbacks_run( * PropertiesChanged signals broadcast contents * anyway. */ - r = invoke_property_get(bus, c->vtable, m->path, c->interface, c->member, reply, u, &error); + r = invoke_property_get(bus, slot, c->vtable, m->path, c->interface, c->member, reply, u, &error); if (r < 0) return bus_maybe_reply_error(m, r, &error); @@ -598,7 +629,7 @@ static int property_get_set_callbacks_run( if (r < 0) return bus_maybe_reply_error(m, r, &error); - r = invoke_property_set(bus, c->vtable, m->path, c->interface, c->member, m, u, &error); + r = invoke_property_set(bus, slot, c->vtable, m->path, c->interface, c->member, m, u, &error); if (r < 0) return bus_maybe_reply_error(m, r, &error); @@ -626,6 +657,7 @@ static int vtable_append_one_property( void *userdata, sd_bus_error *error) { + sd_bus_slot *slot; int r; assert(bus); @@ -646,7 +678,9 @@ static int vtable_append_one_property( if (r < 0) return r; - r = invoke_property_get(bus, v, path, c->interface, v->x.property.member, reply, vtable_property_convert_userdata(v, userdata), error); + slot = container_of(c, sd_bus_slot, node_vtable); + + r = invoke_property_get(bus, slot, v, path, c->interface, v->x.property.member, reply, vtable_property_convert_userdata(v, userdata), error); if (r < 0) return r; if (bus->nodes_modified) @@ -783,7 +817,7 @@ static bool bus_node_with_object_manager(sd_bus *bus, struct node *n) { assert(bus); assert(n); - if (n->object_manager) + if (n->object_managers) return true; if (n->parent) @@ -827,7 +861,7 @@ static bool bus_node_exists( return false; } - return !require_fallback && (n->enumerators || n->object_manager); + return !require_fallback && (n->enumerators || n->object_managers); } static int process_introspect( @@ -1421,7 +1455,7 @@ static struct node *bus_node_allocate(sd_bus *bus, const char *path) { return n; } -static void bus_node_gc(sd_bus *b, struct node *n) { +void bus_node_gc(sd_bus *b, struct node *n) { assert(b); if (!n) @@ -1431,7 +1465,7 @@ static void bus_node_gc(sd_bus *b, struct node *n) { n->callbacks || n->vtables || n->enumerators || - n->object_manager) + n->object_managers) return; assert(hashmap_remove(b->nodes, n->path) == n); @@ -1446,12 +1480,13 @@ static void bus_node_gc(sd_bus *b, struct node *n) { static int bus_add_object( sd_bus *bus, + sd_bus_slot **slot, bool fallback, const char *path, sd_bus_message_handler_t callback, void *userdata) { - struct node_callback *c; + sd_bus_slot *s; struct node *n; int r; @@ -1464,136 +1499,49 @@ static int bus_add_object( if (!n) return -ENOMEM; - c = new0(struct node_callback, 1); - if (!c) { + s = bus_slot_allocate(bus, !slot, BUS_NODE_CALLBACK, sizeof(struct node_callback), userdata); + if (!s) { r = -ENOMEM; goto fail; } - c->node = n; - c->callback = callback; - c->userdata = userdata; - c->is_fallback = fallback; + s->node_callback.callback = callback; + s->node_callback.is_fallback = fallback; - LIST_PREPEND(callbacks, n->callbacks, c); + s->node_callback.node = n; + LIST_PREPEND(callbacks, n->callbacks, &s->node_callback); bus->nodes_modified = true; + if (slot) + *slot = s; + return 0; fail: - free(c); + sd_bus_slot_unref(s); bus_node_gc(bus, n); + return r; } -static int bus_remove_object( +_public_ int sd_bus_add_object( sd_bus *bus, - bool fallback, + sd_bus_slot **slot, const char *path, sd_bus_message_handler_t callback, void *userdata) { - struct node_callback *c; - struct node *n; - - assert_return(bus, -EINVAL); - assert_return(object_path_is_valid(path), -EINVAL); - assert_return(callback, -EINVAL); - assert_return(!bus_pid_changed(bus), -ECHILD); - - n = hashmap_get(bus->nodes, path); - if (!n) - return 0; - - LIST_FOREACH(callbacks, c, n->callbacks) - if (c->callback == callback && c->userdata == userdata && c->is_fallback == fallback) - break; - if (!c) - return 0; - - LIST_REMOVE(callbacks, n->callbacks, c); - free(c); - - bus_node_gc(bus, n); - bus->nodes_modified = true; - - return 1; -} - -_public_ int sd_bus_add_object(sd_bus *bus, - const char *path, - sd_bus_message_handler_t callback, - void *userdata) { - - return bus_add_object(bus, false, path, callback, userdata); -} - -_public_ int sd_bus_remove_object(sd_bus *bus, - const char *path, - sd_bus_message_handler_t callback, - void *userdata) { - - return bus_remove_object(bus, false, path, callback, userdata); -} - -_public_ int sd_bus_add_fallback(sd_bus *bus, - const char *prefix, - sd_bus_message_handler_t callback, - void *userdata) { - - return bus_add_object(bus, true, prefix, callback, userdata); -} - -_public_ int sd_bus_remove_fallback(sd_bus *bus, - const char *prefix, - sd_bus_message_handler_t callback, - void *userdata) { - - return bus_remove_object(bus, true, prefix, callback, userdata); + return bus_add_object(bus, slot, false, path, callback, userdata); } -static void free_node_vtable(sd_bus *bus, struct node_vtable *w) { - assert(bus); - - if (!w) - return; - - if (w->interface && w->node && w->vtable) { - const sd_bus_vtable *v; - - for (v = w->vtable; v->type != _SD_BUS_VTABLE_END; v++) { - struct vtable_member *x = NULL; - - switch (v->type) { - - case _SD_BUS_VTABLE_METHOD: { - struct vtable_member key; - - key.path = w->node->path; - key.interface = w->interface; - key.member = v->x.method.member; - - x = hashmap_remove(bus->vtable_methods, &key); - break; - } - - case _SD_BUS_VTABLE_PROPERTY: - case _SD_BUS_VTABLE_WRITABLE_PROPERTY: { - struct vtable_member key; - - key.path = w->node->path; - key.interface = w->interface; - key.member = v->x.property.member; - x = hashmap_remove(bus->vtable_properties, &key); - break; - }} - - free(x); - } - } +_public_ int sd_bus_add_fallback( + sd_bus *bus, + sd_bus_slot **slot, + const char *prefix, + sd_bus_message_handler_t callback, + void *userdata) { - free(w->interface); - free(w); + return bus_add_object(bus, slot, true, prefix, callback, userdata); } static unsigned long vtable_member_hash_func(const void *a, const uint8_t hash_key[HASH_KEY_SIZE]) { @@ -1637,6 +1585,7 @@ static int vtable_member_compare_func(const void *a, const void *b) { static int add_object_vtable_internal( sd_bus *bus, + sd_bus_slot **slot, const char *path, const char *interface, const sd_bus_vtable *vtable, @@ -1644,7 +1593,8 @@ static int add_object_vtable_internal( sd_bus_object_find_t find, void *userdata) { - struct node_vtable *c = NULL, *i, *existing = NULL; + sd_bus_slot *s; + struct node_vtable *i, *existing = NULL; const sd_bus_vtable *v; struct node *n; int r; @@ -1690,25 +1640,23 @@ static int add_object_vtable_internal( } } - c = new0(struct node_vtable, 1); - if (!c) { + s = bus_slot_allocate(bus, !slot, BUS_NODE_VTABLE, sizeof(struct node_vtable), userdata); + if (!s) { r = -ENOMEM; goto fail; } - c->node = n; - c->is_fallback = fallback; - c->vtable = vtable; - c->userdata = userdata; - c->find = find; + s->node_vtable.is_fallback = fallback; + s->node_vtable.vtable = vtable; + s->node_vtable.find = find; - c->interface = strdup(interface); - if (!c->interface) { + s->node_vtable.interface = strdup(interface); + if (!s->node_vtable.interface) { r = -ENOMEM; goto fail; } - for (v = c->vtable+1; v->type != _SD_BUS_VTABLE_END; v++) { + for (v = s->node_vtable.vtable+1; v->type != _SD_BUS_VTABLE_END; v++) { switch (v->type) { @@ -1730,9 +1678,9 @@ static int add_object_vtable_internal( goto fail; } - m->parent = c; + m->parent = &s->node_vtable; m->path = n->path; - m->interface = c->interface; + m->interface = s->node_vtable.interface; m->member = v->x.method.member; m->vtable = v; @@ -1773,9 +1721,9 @@ static int add_object_vtable_internal( goto fail; } - m->parent = c; + m->parent = &s->node_vtable; m->path = n->path; - m->interface = c->interface; + m->interface = s->node_vtable.interface; m->member = v->x.property.member; m->vtable = v; @@ -1805,110 +1753,53 @@ static int add_object_vtable_internal( } } - LIST_INSERT_AFTER(vtables, n->vtables, existing, c); + s->node_vtable.node = n; + LIST_INSERT_AFTER(vtables, n->vtables, existing, &s->node_vtable); bus->nodes_modified = true; + if (slot) + *slot = s; + return 0; fail: - if (c) - free_node_vtable(bus, c); - - bus_node_gc(bus, n); - return r; -} - -static int remove_object_vtable_internal( - sd_bus *bus, - const char *path, - const char *interface, - const sd_bus_vtable *vtable, - bool fallback, - sd_bus_object_find_t find, - void *userdata) { - - struct node_vtable *c; - struct node *n; - - assert_return(bus, -EINVAL); - assert_return(object_path_is_valid(path), -EINVAL); - assert_return(interface_name_is_valid(interface), -EINVAL); - assert_return(!bus_pid_changed(bus), -ECHILD); - - n = hashmap_get(bus->nodes, path); - if (!n) - return 0; - - LIST_FOREACH(vtables, c, n->vtables) - if (streq(c->interface, interface) && - c->is_fallback == fallback && - c->vtable == vtable && - c->find == find && - c->userdata == userdata) - break; - - if (!c) - return 0; - - LIST_REMOVE(vtables, n->vtables, c); - - free_node_vtable(bus, c); + sd_bus_slot_unref(s); bus_node_gc(bus, n); - bus->nodes_modified = true; - - return 1; + return r; } _public_ int sd_bus_add_object_vtable( sd_bus *bus, + sd_bus_slot **slot, const char *path, const char *interface, const sd_bus_vtable *vtable, void *userdata) { - return add_object_vtable_internal(bus, path, interface, vtable, false, NULL, userdata); -} - -_public_ int sd_bus_remove_object_vtable( - sd_bus *bus, - const char *path, - const char *interface, - const sd_bus_vtable *vtable, - void *userdata) { - - return remove_object_vtable_internal(bus, path, interface, vtable, false, NULL, userdata); + return add_object_vtable_internal(bus, slot, path, interface, vtable, false, NULL, userdata); } _public_ int sd_bus_add_fallback_vtable( sd_bus *bus, - const char *path, - const char *interface, - const sd_bus_vtable *vtable, - sd_bus_object_find_t find, - void *userdata) { - - return add_object_vtable_internal(bus, path, interface, vtable, true, find, userdata); -} - -_public_ int sd_bus_remove_fallback_vtable( - sd_bus *bus, - const char *path, + sd_bus_slot **slot, + const char *prefix, const char *interface, const sd_bus_vtable *vtable, sd_bus_object_find_t find, void *userdata) { - return remove_object_vtable_internal(bus, path, interface, vtable, true, find, userdata); + return add_object_vtable_internal(bus, slot, prefix, interface, vtable, true, find, userdata); } _public_ int sd_bus_add_node_enumerator( sd_bus *bus, + sd_bus_slot **slot, const char *path, sd_bus_node_enumerator_t callback, void *userdata) { - struct node_enumerator *c; + sd_bus_slot *s; struct node *n; int r; @@ -1921,61 +1812,28 @@ _public_ int sd_bus_add_node_enumerator( if (!n) return -ENOMEM; - c = new0(struct node_enumerator, 1); - if (!c) { + s = bus_slot_allocate(bus, !slot, BUS_NODE_ENUMERATOR, sizeof(struct node_enumerator), userdata); + if (!s) { r = -ENOMEM; goto fail; } - c->node = n; - c->callback = callback; - c->userdata = userdata; - - LIST_PREPEND(enumerators, n->enumerators, c); + s->node_enumerator.callback = callback; + s->node_enumerator.node = n; + LIST_PREPEND(enumerators, n->enumerators, &s->node_enumerator); bus->nodes_modified = true; + if (slot) + *slot = s; + return 0; fail: - free(c); - bus_node_gc(bus, n); - return r; -} - -_public_ int sd_bus_remove_node_enumerator( - sd_bus *bus, - const char *path, - sd_bus_node_enumerator_t callback, - void *userdata) { - - struct node_enumerator *c; - struct node *n; - - assert_return(bus, -EINVAL); - assert_return(object_path_is_valid(path), -EINVAL); - assert_return(callback, -EINVAL); - assert_return(!bus_pid_changed(bus), -ECHILD); - - n = hashmap_get(bus->nodes, path); - if (!n) - return 0; - - LIST_FOREACH(enumerators, c, n->enumerators) - if (c->callback == callback && c->userdata == userdata) - break; - - if (!c) - return 0; - - LIST_REMOVE(enumerators, n->enumerators, c); - free(c); - + sd_bus_slot_unref(s); bus_node_gc(bus, n); - bus->nodes_modified = true; - - return 1; + return r; } static int emit_properties_changed_on_interface( @@ -2481,8 +2339,10 @@ _public_ int sd_bus_emit_interfaces_removed(sd_bus *bus, const char *path, const return sd_bus_emit_interfaces_removed_strv(bus, path, interfaces); } -_public_ int sd_bus_add_object_manager(sd_bus *bus, const char *path) { +_public_ int sd_bus_add_object_manager(sd_bus *bus, sd_bus_slot **slot, const char *path) { + sd_bus_slot *s; struct node *n; + int r; assert_return(bus, -EINVAL); assert_return(object_path_is_valid(path), -EINVAL); @@ -2492,28 +2352,24 @@ _public_ int sd_bus_add_object_manager(sd_bus *bus, const char *path) { if (!n) return -ENOMEM; - n->object_manager = true; - bus->nodes_modified = true; - return 0; -} - -_public_ int sd_bus_remove_object_manager(sd_bus *bus, const char *path) { - struct node *n; + s = bus_slot_allocate(bus, !slot, BUS_NODE_OBJECT_MANAGER, sizeof(struct node_object_manager), NULL); + if (!s) { + r = -ENOMEM; + goto fail; + } - assert_return(bus, -EINVAL); - assert_return(object_path_is_valid(path), -EINVAL); - assert_return(!bus_pid_changed(bus), -ECHILD); + s->node_object_manager.node = n; + LIST_PREPEND(object_managers, n->object_managers, &s->node_object_manager); + bus->nodes_modified = true; - n = hashmap_get(bus->nodes, path); - if (!n) - return 0; + if (slot) + *slot = s; - if (!n->object_manager) - return 0; + return 0; - n->object_manager = false; - bus->nodes_modified = true; +fail: + sd_bus_slot_unref(s); bus_node_gc(bus, n); - return 1; + return r; } diff --git a/src/libsystemd/sd-bus/bus-objects.h b/src/libsystemd/sd-bus/bus-objects.h index 420edd9478..4373fae89c 100644 --- a/src/libsystemd/sd-bus/bus-objects.h +++ b/src/libsystemd/sd-bus/bus-objects.h @@ -24,3 +24,4 @@ #include "bus-internal.h" int bus_process_object(sd_bus *bus, sd_bus_message *m); +void bus_node_gc(sd_bus *b, struct node *n); diff --git a/src/libsystemd/sd-bus/bus-slot.c b/src/libsystemd/sd-bus/bus-slot.c new file mode 100644 index 0000000000..8e38992ec4 --- /dev/null +++ b/src/libsystemd/sd-bus/bus-slot.c @@ -0,0 +1,244 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +/*** + This file is part of systemd. + + Copyright 2013 Lennart Poettering + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see <http://www.gnu.org/licenses/>. +***/ + +#include "sd-bus.h" +#include "bus-control.h" +#include "bus-objects.h" +#include "bus-slot.h" + +sd_bus_slot *bus_slot_allocate( + sd_bus *bus, + bool floating, + BusSlotType type, + size_t extra, + void *userdata) { + + sd_bus_slot *slot; + + assert(bus); + + slot = malloc0(offsetof(sd_bus_slot, reply_callback) + extra); + if (!slot) + return NULL; + + slot->n_ref = 1; + slot->type = type; + slot->bus = bus; + slot->floating = floating; + slot->userdata = userdata; + + if (!floating) + sd_bus_ref(bus); + + LIST_PREPEND(slots, bus->slots, slot); + + return slot; +} + +_public_ sd_bus_slot* sd_bus_slot_ref(sd_bus_slot *slot) { + assert_return(slot, NULL); + + assert(slot->n_ref > 0); + + slot->n_ref++; + return slot; +} + +void bus_slot_disconnect(sd_bus_slot *slot) { + sd_bus *bus; + + assert(slot); + + switch (slot->type) { + + case _BUS_SLOT_DISCONNECTED: + /* Already disconnected... */ + return; + + case BUS_REPLY_CALLBACK: + + if (slot->reply_callback.cookie != 0) + hashmap_remove(slot->bus->reply_callbacks, &slot->reply_callback.cookie); + + if (slot->reply_callback.timeout != 0) + prioq_remove(slot->bus->reply_callbacks_prioq, &slot->reply_callback, &slot->reply_callback.prioq_idx); + + break; + + case BUS_FILTER_CALLBACK: + slot->bus->filter_callbacks_modified = true; + LIST_REMOVE(callbacks, slot->bus->filter_callbacks, &slot->filter_callback); + break; + + case BUS_MATCH_CALLBACK: + + if (slot->bus->bus_client) + bus_remove_match_internal(slot->bus, slot->match_callback.match_string, slot->match_callback.cookie); + + slot->bus->match_callbacks_modified = true; + bus_match_remove(&slot->bus->match_callbacks, &slot->match_callback); + + free(slot->match_callback.match_string); + + break; + + case BUS_NODE_CALLBACK: + + if (slot->node_callback.node) { + LIST_REMOVE(callbacks, slot->node_callback.node->callbacks, &slot->node_callback); + slot->bus->nodes_modified = true; + + bus_node_gc(slot->bus, slot->node_callback.node); + } + + break; + + case BUS_NODE_ENUMERATOR: + + if (slot->node_enumerator.node) { + LIST_REMOVE(enumerators, slot->node_enumerator.node->enumerators, &slot->node_enumerator); + slot->bus->nodes_modified = true; + + bus_node_gc(slot->bus, slot->node_enumerator.node); + } + + break; + + case BUS_NODE_OBJECT_MANAGER: + + if (slot->node_object_manager.node) { + LIST_REMOVE(object_managers, slot->node_object_manager.node->object_managers, &slot->node_object_manager); + slot->bus->nodes_modified = true; + + bus_node_gc(slot->bus, slot->node_object_manager.node); + } + + break; + + case BUS_NODE_VTABLE: + + if (slot->node_vtable.node && slot->node_vtable.interface && slot->node_vtable.vtable) { + const sd_bus_vtable *v; + + for (v = slot->node_vtable.vtable; v->type != _SD_BUS_VTABLE_END; v++) { + struct vtable_member *x = NULL; + + switch (v->type) { + + case _SD_BUS_VTABLE_METHOD: { + struct vtable_member key; + + key.path = slot->node_vtable.node->path; + key.interface = slot->node_vtable.interface; + key.member = v->x.method.member; + + x = hashmap_remove(slot->bus->vtable_methods, &key); + break; + } + + case _SD_BUS_VTABLE_PROPERTY: + case _SD_BUS_VTABLE_WRITABLE_PROPERTY: { + struct vtable_member key; + + key.path = slot->node_vtable.node->path; + key.interface = slot->node_vtable.interface; + key.member = v->x.method.member; + + + x = hashmap_remove(slot->bus->vtable_properties, &key); + break; + }} + + free(x); + } + } + + free(slot->node_vtable.interface); + + if (slot->node_vtable.node) { + LIST_REMOVE(vtables, slot->node_vtable.node->vtables, &slot->node_vtable); + slot->bus->nodes_modified = true; + + bus_node_gc(slot->bus, slot->node_vtable.node); + } + + break; + } + bus = slot->bus; + + slot->type = _BUS_SLOT_DISCONNECTED; + slot->bus = NULL; + LIST_REMOVE(slots, bus->slots, slot); + + if (!slot->floating) + sd_bus_unref(bus); +} + +_public_ sd_bus_slot* sd_bus_slot_unref(sd_bus_slot *slot) { + + if (!slot) + return NULL; + + assert(slot->n_ref > 0); + + if (slot->n_ref > 1) { + slot->n_ref --; + return NULL; + } + + bus_slot_disconnect(slot); + free(slot); + + return NULL; +} + +_public_ sd_bus* sd_bus_slot_get_bus(sd_bus_slot *slot) { + assert_return(slot, NULL); + + return slot->bus; +} + +_public_ void *sd_bus_slot_get_userdata(sd_bus_slot *slot) { + assert_return(slot, NULL); + + return slot->userdata; +} + +_public_ void *sd_bus_slot_set_userdata(sd_bus_slot *slot, void *userdata) { + void *ret; + + assert_return(slot, NULL); + + ret = slot->userdata; + slot->userdata = userdata; + + return ret; +} + +_public_ sd_bus_message *sd_bus_slot_get_current_message(sd_bus_slot *slot) { + assert_return(slot, NULL); + assert_return(slot->type != _BUS_SLOT_DISCONNECTED, NULL); + + if (slot->bus->current_slot != slot) + return NULL; + + return slot->bus->current_message; +} diff --git a/src/libsystemd/sd-bus/bus-slot.h b/src/libsystemd/sd-bus/bus-slot.h new file mode 100644 index 0000000000..23a15e4d02 --- /dev/null +++ b/src/libsystemd/sd-bus/bus-slot.h @@ -0,0 +1,29 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +#pragma once + +/*** + This file is part of systemd. + + Copyright 2014 Lennart Poettering + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see <http://www.gnu.org/licenses/>. +***/ + +#include "sd-bus.h" +#include "bus-internal.h" + +sd_bus_slot *bus_slot_allocate(sd_bus *bus, bool floating, BusSlotType type, size_t extra, void *userdata); + +void bus_slot_disconnect(sd_bus_slot *slot); diff --git a/src/libsystemd/sd-bus/bus-track.c b/src/libsystemd/sd-bus/bus-track.c index 0f6a2eafbd..ffa2cf3d75 100644 --- a/src/libsystemd/sd-bus/bus-track.c +++ b/src/libsystemd/sd-bus/bus-track.c @@ -21,6 +21,7 @@ #include "sd-bus.h" #include "set.h" +#include "bus-util.h" #include "bus-internal.h" #include "bus-track.h" @@ -29,7 +30,7 @@ struct sd_bus_track { sd_bus *bus; sd_bus_track_handler_t handler; void *userdata; - Set *names; + Hashmap *names; LIST_FIELDS(sd_bus_track, queue); Iterator iterator; bool in_queue; @@ -128,11 +129,11 @@ _public_ sd_bus_track* sd_bus_track_unref(sd_bus_track *track) { return NULL; } - while ((n = set_first(track->names))) + while ((n = hashmap_first_key(track->names))) sd_bus_track_remove_name(track, n); bus_track_remove_from_queue(track); - set_free(track->names); + hashmap_free(track->names); sd_bus_unref(track->bus); free(track); @@ -157,6 +158,7 @@ static int on_name_owner_changed(sd_bus *bus, sd_bus_message *message, void *use } _public_ int sd_bus_track_add_name(sd_bus_track *track, const char *name) { + _cleanup_bus_slot_unref_ sd_bus_slot *slot = NULL; _cleanup_free_ char *n = NULL; const char *match; int r; @@ -164,7 +166,7 @@ _public_ int sd_bus_track_add_name(sd_bus_track *track, const char *name) { assert_return(track, -EINVAL); assert_return(service_name_is_valid(name), -EINVAL); - r = set_ensure_allocated(&track->names, string_hash_func, string_compare_func); + r = hashmap_ensure_allocated(&track->names, string_hash_func, string_compare_func); if (r < 0) return r; @@ -172,30 +174,28 @@ _public_ int sd_bus_track_add_name(sd_bus_track *track, const char *name) { if (!n) return -ENOMEM; - r = set_put(track->names, n); + /* First, subscribe to this name */ + match = MATCH_FOR_NAME(n); + r = sd_bus_add_match(track->bus, &slot, match, on_name_owner_changed, track); + if (r < 0) + return r; + + r = hashmap_put(track->names, n, slot); if (r == -EEXIST) return 0; if (r < 0) return r; - /* First, subscribe to this name */ - match = MATCH_FOR_NAME(name); - r = sd_bus_add_match(track->bus, match, on_name_owner_changed, track); - if (r < 0) { - set_remove(track->names, n); - return r; - } - /* Second, check if it is currently existing, or maybe * doesn't, or maybe disappeared already. */ - r = sd_bus_get_owner(track->bus, name, 0, NULL); + r = sd_bus_get_owner(track->bus, n, 0, NULL); if (r < 0) { - set_remove(track->names, n); - sd_bus_remove_match(track->bus, match, on_name_owner_changed, track); + hashmap_remove(track->names, n); return r; } n = NULL; + slot = NULL; bus_track_remove_from_queue(track); track->modified = true; @@ -204,22 +204,19 @@ _public_ int sd_bus_track_add_name(sd_bus_track *track, const char *name) { } _public_ int sd_bus_track_remove_name(sd_bus_track *track, const char *name) { - const char *match; - _cleanup_free_ char *n = NULL;; + _cleanup_bus_slot_unref_ sd_bus_slot *slot = NULL; + _cleanup_free_ char *n = NULL; assert_return(name, -EINVAL); if (!track) return 0; - n = set_remove(track->names, (char*) name); - if (!n) + slot = hashmap_remove2(track->names, (char*) name, (void**) &n); + if (!slot) return 0; - match = MATCH_FOR_NAME(n); - sd_bus_remove_match(track->bus, match, on_name_owner_changed, track); - - if (set_isempty(track->names)) + if (hashmap_isempty(track->names)) bus_track_add_to_queue(track); track->modified = true; @@ -231,34 +228,40 @@ _public_ unsigned sd_bus_track_count(sd_bus_track *track) { if (!track) return 0; - return set_size(track->names); + return hashmap_size(track->names); } _public_ const char* sd_bus_track_contains(sd_bus_track *track, const char *name) { assert_return(track, NULL); assert_return(name, NULL); - return set_get(track->names, (void*) name); + return hashmap_get(track->names, (void*) name) ? name : NULL; } _public_ const char* sd_bus_track_first(sd_bus_track *track) { + const char *n = NULL; + if (!track) return NULL; track->modified = false; track->iterator = NULL; - return set_iterate(track->names, &track->iterator); + hashmap_iterate(track->names, &track->iterator, (const void**) &n); + return n; } _public_ const char* sd_bus_track_next(sd_bus_track *track) { + const char *n = NULL; + if (!track) return NULL; if (track->modified) return NULL; - return set_iterate(track->names, &track->iterator); + hashmap_iterate(track->names, &track->iterator, (const void**) &n); + return n; } _public_ int sd_bus_track_add_sender(sd_bus_track *track, sd_bus_message *m) { diff --git a/src/libsystemd/sd-bus/bus-util.c b/src/libsystemd/sd-bus/bus-util.c index 84b3fc5af5..b5b3c857b8 100644 --- a/src/libsystemd/sd-bus/bus-util.c +++ b/src/libsystemd/sd-bus/bus-util.c @@ -77,7 +77,7 @@ int bus_async_unregister_and_exit(sd_event *e, sd_bus *bus, const char *name) { if (r < 0) return -ENOMEM; - r = sd_bus_add_match(bus, match, name_owner_change_callback, e); + r = sd_bus_add_match(bus, NULL, match, name_owner_change_callback, e); if (r < 0) return r; @@ -251,17 +251,16 @@ typedef struct AsyncPolkitQuery { sd_bus_message *request, *reply; sd_bus_message_handler_t callback; void *userdata; - uint64_t serial; + sd_bus_slot *slot; Hashmap *registry; } AsyncPolkitQuery; -static void async_polkit_query_free(sd_bus *b, AsyncPolkitQuery *q) { +static void async_polkit_query_free(AsyncPolkitQuery *q) { if (!q) return; - if (q->serial > 0 && b) - sd_bus_call_async_cancel(b, q->serial); + sd_bus_slot_unref(q->slot); if (q->registry && q->request) hashmap_remove(q->registry, q->request); @@ -281,8 +280,8 @@ static int async_polkit_callback(sd_bus *bus, sd_bus_message *reply, void *userd assert(reply); assert(q); + q->slot = sd_bus_slot_unref(q->slot); q->reply = sd_bus_message_ref(reply); - q->serial = 0; r = sd_bus_message_rewind(q->request, true); if (r < 0) { @@ -294,7 +293,8 @@ static int async_polkit_callback(sd_bus *bus, sd_bus_message *reply, void *userd r = bus_maybe_reply_error(q->request, r, &error_buffer); finish: - async_polkit_query_free(bus, q); + async_polkit_query_free(q); + return r; } @@ -413,15 +413,15 @@ int bus_verify_polkit_async( r = hashmap_put(*registry, m, q); if (r < 0) { - async_polkit_query_free(bus, q); + async_polkit_query_free(q); return r; } q->registry = *registry; - r = sd_bus_call_async(bus, pk, async_polkit_callback, q, 0, &q->serial); + r = sd_bus_call_async(bus, &q->slot, pk, async_polkit_callback, q, 0); if (r < 0) { - async_polkit_query_free(bus, q); + async_polkit_query_free(q); return r; } @@ -436,7 +436,7 @@ void bus_verify_polkit_async_registry_free(sd_bus *bus, Hashmap *registry) { AsyncPolkitQuery *q; while ((q = hashmap_steal_first(registry))) - async_polkit_query_free(bus, q); + async_polkit_query_free(q); hashmap_free(registry); #endif diff --git a/src/libsystemd/sd-bus/bus-util.h b/src/libsystemd/sd-bus/bus-util.h index 8103555fe8..1514fad81f 100644 --- a/src/libsystemd/sd-bus/bus-util.h +++ b/src/libsystemd/sd-bus/bus-util.h @@ -139,12 +139,16 @@ typedef struct UnitInfo { int bus_parse_unit_info(sd_bus_message *message, UnitInfo *u); DEFINE_TRIVIAL_CLEANUP_FUNC(sd_bus*, sd_bus_unref); +DEFINE_TRIVIAL_CLEANUP_FUNC(sd_bus_slot*, sd_bus_slot_unref); DEFINE_TRIVIAL_CLEANUP_FUNC(sd_bus_message*, sd_bus_message_unref); DEFINE_TRIVIAL_CLEANUP_FUNC(sd_bus_creds*, sd_bus_creds_unref); +DEFINE_TRIVIAL_CLEANUP_FUNC(sd_bus_track*, sd_bus_track_unref); #define _cleanup_bus_unref_ _cleanup_(sd_bus_unrefp) +#define _cleanup_bus_slot_unref_ _cleanup_(sd_bus_slot_unrefp) #define _cleanup_bus_message_unref_ _cleanup_(sd_bus_message_unrefp) #define _cleanup_bus_creds_unref_ _cleanup_(sd_bus_creds_unrefp) +#define _cleanup_bus_track_unref_ _cleanup_(sd_bus_slot_unrefp) #define _cleanup_bus_error_free_ _cleanup_(sd_bus_error_free) #define BUS_DEFINE_PROPERTY_GET_ENUM(function, name, type) \ diff --git a/src/libsystemd/sd-bus/busctl.c b/src/libsystemd/sd-bus/busctl.c index 4e396f20c1..4545047011 100644 --- a/src/libsystemd/sd-bus/busctl.c +++ b/src/libsystemd/sd-bus/busctl.c @@ -240,7 +240,7 @@ static int monitor(sd_bus *bus, char *argv[]) { if (!m) return log_oom(); - r = sd_bus_add_match(bus, m, NULL, NULL); + r = sd_bus_add_match(bus, NULL, m, NULL, NULL); if (r < 0) { log_error("Failed to add match: %s", strerror(-r)); return r; @@ -250,7 +250,7 @@ static int monitor(sd_bus *bus, char *argv[]) { } STRV_FOREACH(i, arg_matches) { - r = sd_bus_add_match(bus, *i, NULL, NULL); + r = sd_bus_add_match(bus, NULL, *i, NULL, NULL); if (r < 0) { log_error("Failed to add match: %s", strerror(-r)); return r; @@ -260,7 +260,7 @@ static int monitor(sd_bus *bus, char *argv[]) { } if (!added_something) { - r = sd_bus_add_match(bus, "", NULL, NULL); + r = sd_bus_add_match(bus, NULL, "", NULL, NULL); if (r < 0) { log_error("Failed to add match: %s", strerror(-r)); return r; diff --git a/src/libsystemd/sd-bus/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c index dc54e211a4..ea80e9d19b 100644 --- a/src/libsystemd/sd-bus/sd-bus.c +++ b/src/libsystemd/sd-bus/sd-bus.c @@ -52,6 +52,7 @@ #include "bus-container.h" #include "bus-protocol.h" #include "bus-track.h" +#include "bus-slot.h" static int bus_poll(sd_bus *bus, bool need_more, uint64_t timeout_usec); static int attach_io_events(sd_bus *b); @@ -71,43 +72,6 @@ static void bus_close_fds(sd_bus *b) { b->input_fd = b->output_fd = -1; } -static void bus_node_destroy(sd_bus *b, struct node *n) { - struct node_callback *c; - struct node_vtable *v; - struct node_enumerator *e; - - assert(b); - - if (!n) - return; - - while (n->child) - bus_node_destroy(b, n->child); - - while ((c = n->callbacks)) { - LIST_REMOVE(callbacks, n->callbacks, c); - free(c); - } - - while ((v = n->vtables)) { - LIST_REMOVE(vtables, n->vtables, v); - free(v->interface); - free(v); - } - - while ((e = n->enumerators)) { - LIST_REMOVE(enumerators, n->enumerators, e); - free(e); - } - - if (n->parent) - LIST_REMOVE(siblings, n->parent->child, n); - - assert_se(hashmap_remove(b->nodes, n->path) == n); - free(n->path); - free(n); -} - static void bus_reset_queues(sd_bus *b) { assert(b); @@ -133,15 +97,28 @@ static void bus_reset_queues(sd_bus *b) { } static void bus_free(sd_bus *b) { - struct filter_callback *f; - struct node *n; + sd_bus_slot *s; assert(b); - assert(!b->track_queue); + b->state = BUS_CLOSED; + sd_bus_detach_event(b); + while ((s = b->slots)) { + /* At this point only floating slots can still be + * around, because the non-floating ones keep a + * reference to the bus, and we thus couldn't be + * destructing right now... We forcibly disconnect the + * slots here, so that they still can be referenced by + * apps, but are dead. */ + + assert(s->floating); + bus_slot_disconnect(s); + sd_bus_slot_unref(s); + } + if (b->default_bus_ptr) *b->default_bus_ptr = NULL; @@ -171,19 +148,12 @@ static void bus_free(sd_bus *b) { hashmap_free_free(b->reply_callbacks); prioq_free(b->reply_callbacks_prioq); - while ((f = b->filter_callbacks)) { - LIST_REMOVE(callbacks, b->filter_callbacks, f); - free(f); - } - bus_match_free(&b->match_callbacks); hashmap_free_free(b->vtable_methods); hashmap_free_free(b->vtable_properties); - while ((n = hashmap_first(b->nodes))) - bus_node_destroy(b, n); - + assert(hashmap_isempty(b->nodes)); hashmap_free(b->nodes); bus_kernel_flush_memfd(b); @@ -426,7 +396,7 @@ static int bus_send_hello(sd_bus *bus) { if (r < 0) return r; - return sd_bus_call_async(bus, m, hello_callback, NULL, 0, &bus->hello_cookie); + return sd_bus_call_async(bus, NULL, m, hello_callback, NULL, 0); } int bus_start_running(sd_bus *bus) { @@ -1793,14 +1763,14 @@ static int timeout_compare(const void *a, const void *b) { _public_ int sd_bus_call_async( sd_bus *bus, + sd_bus_slot **slot, sd_bus_message *_m, sd_bus_message_handler_t callback, void *userdata, - uint64_t usec, - uint64_t *cookie) { + uint64_t usec) { _cleanup_bus_message_unref_ sd_bus_message *m = sd_bus_message_ref(_m); - struct reply_callback *c; + _cleanup_bus_slot_unref_ sd_bus_slot *s = NULL; int r; assert_return(bus, -EINVAL); @@ -1830,55 +1800,37 @@ _public_ int sd_bus_call_async( if (r < 0) return r; - c = new0(struct reply_callback, 1); - if (!c) + s = bus_slot_allocate(bus, !slot, BUS_REPLY_CALLBACK, sizeof(struct reply_callback), userdata); + if (!s) return -ENOMEM; - c->callback = callback; - c->userdata = userdata; - c->cookie = BUS_MESSAGE_COOKIE(m); - c->timeout = calc_elapse(m->timeout); + s->reply_callback.callback = callback; - r = hashmap_put(bus->reply_callbacks, &c->cookie, c); + s->reply_callback.cookie = BUS_MESSAGE_COOKIE(m); + r = hashmap_put(bus->reply_callbacks, &s->reply_callback.cookie, &s->reply_callback); if (r < 0) { - free(c); + s->reply_callback.cookie = 0; return r; } - if (c->timeout != 0) { - r = prioq_put(bus->reply_callbacks_prioq, c, &c->prioq_idx); + s->reply_callback.timeout = calc_elapse(m->timeout); + if (s->reply_callback.timeout != 0) { + r = prioq_put(bus->reply_callbacks_prioq, &s->reply_callback, &s->reply_callback.prioq_idx); if (r < 0) { - c->timeout = 0; - sd_bus_call_async_cancel(bus, c->cookie); + s->reply_callback.timeout = 0; return r; } } - r = sd_bus_send(bus, m, cookie); - if (r < 0) { - sd_bus_call_async_cancel(bus, c->cookie); + r = sd_bus_send(bus, m, &s->reply_callback.cookie); + if (r < 0) return r; - } - - return r; -} - -_public_ int sd_bus_call_async_cancel(sd_bus *bus, uint64_t cookie) { - struct reply_callback *c; - assert_return(bus, -EINVAL); - assert_return(cookie != 0, -EINVAL); - assert_return(!bus_pid_changed(bus), -ECHILD); - - c = hashmap_remove(bus->reply_callbacks, &cookie); - if (!c) - return 0; - - if (c->timeout != 0) - prioq_remove(bus->reply_callbacks_prioq, c, &c->prioq_idx); + if (slot) + *slot = s; + s = NULL; - free(c); - return 1; + return r; } int bus_ensure_running(sd_bus *bus) { @@ -2125,6 +2077,11 @@ _public_ int sd_bus_get_timeout(sd_bus *bus, uint64_t *timeout_usec) { return 0; } + if (c->timeout == 0) { + *timeout_usec = (uint64_t) -1; + return 0; + } + *timeout_usec = c->timeout; return 1; } @@ -2161,16 +2118,21 @@ static int process_timeout(sd_bus *bus) { return r; assert_se(prioq_pop(bus->reply_callbacks_prioq) == c); + c->timeout = 0; + hashmap_remove(bus->reply_callbacks, &c->cookie); + c->cookie = 0; + + bus->current_message = m; + bus->current_slot = container_of(c, sd_bus_slot, reply_callback); - bus->current = m; bus->iteration_counter ++; - r = c->callback(bus, m, c->userdata, &error_buffer); + r = c->callback(bus, m, bus->current_slot->userdata, &error_buffer); r = bus_maybe_reply_error(m, r, &error_buffer); - free(c); - bus->current = NULL; + bus->current_message = NULL; + bus->current_slot = NULL; return r; } @@ -2191,7 +2153,7 @@ static int process_hello(sd_bus *bus, sd_bus_message *m) { m->header->type != SD_BUS_MESSAGE_METHOD_ERROR) return -EIO; - if (m->reply_cookie != bus->hello_cookie) + if (m->reply_cookie != 1) return -EIO; return 0; @@ -2200,7 +2162,8 @@ static int process_hello(sd_bus *bus, sd_bus_message *m) { static int process_reply(sd_bus *bus, sd_bus_message *m) { _cleanup_bus_message_unref_ sd_bus_message *synthetic_reply = NULL; _cleanup_bus_error_free_ sd_bus_error error_buffer = SD_BUS_ERROR_NULL; - _cleanup_free_ struct reply_callback *c = NULL; + sd_bus_slot *slot; + struct reply_callback *c; int r; assert(bus); @@ -2220,8 +2183,13 @@ static int process_reply(sd_bus *bus, sd_bus_message *m) { if (!c) return 0; - if (c->timeout != 0) + c->cookie = 0; + slot = container_of(c, sd_bus_slot, reply_callback); + + if (c->timeout != 0) { prioq_remove(bus->reply_callbacks_prioq, c, &c->prioq_idx); + c->timeout = 0; + } if (m->n_fds > 0 && !(bus->hello_flags & KDBUS_HELLO_ACCEPT_FD)) { @@ -2234,22 +2202,31 @@ static int process_reply(sd_bus *bus, sd_bus_message *m) { &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INCONSISTENT_MESSAGE, "Reply message contained file descriptor"), &synthetic_reply); if (r < 0) - return r; + goto finish; r = bus_seal_synthetic_message(bus, synthetic_reply); if (r < 0) - return r; + goto finish; m = synthetic_reply; } else { r = sd_bus_message_rewind(m, true); if (r < 0) - return r; + goto finish; } - r = c->callback(bus, m, c->userdata, &error_buffer); + bus->current_slot = slot; + r = c->callback(bus, m, bus->current_slot->userdata, &error_buffer); + bus->current_slot = NULL; + r = bus_maybe_reply_error(m, r, &error_buffer); +finish: + if (slot->floating) { + bus_slot_disconnect(slot); + sd_bus_slot_unref(slot); + } + return r; } @@ -2279,7 +2256,10 @@ static int process_filter(sd_bus *bus, sd_bus_message *m) { if (r < 0) return r; - r = l->callback(bus, m, l->userdata, &error_buffer); + bus->current_slot = container_of(l, sd_bus_slot, filter_callback); + r = l->callback(bus, m, bus->current_slot->userdata, &error_buffer); + bus->current_slot = NULL; + r = bus_maybe_reply_error(m, r, &error_buffer); if (r != 0) return r; @@ -2395,7 +2375,7 @@ static int process_message(sd_bus *bus, sd_bus_message *m) { assert(bus); assert(m); - bus->current = m; + bus->current_message = m; bus->iteration_counter++; log_debug("Got message type=%s sender=%s destination=%s object=%s interface=%s member=%s cookie=%" PRIu64 " reply_cookie=%" PRIu64 " error=%s", @@ -2436,7 +2416,7 @@ static int process_message(sd_bus *bus, sd_bus_message *m) { r = bus_process_object(bus, m); finish: - bus->current = NULL; + bus->current_message = NULL; return r; } @@ -2539,17 +2519,23 @@ static int process_closing(sd_bus *bus, sd_bus_message **ret) { if (r < 0) return r; - if (c->timeout != 0) + if (c->timeout != 0) { prioq_remove(bus->reply_callbacks_prioq, c, &c->prioq_idx); + c->timeout = 0; + } hashmap_remove(bus->reply_callbacks, &c->cookie); + c->cookie = 0; + + bus->current_message = m; + bus->current_slot = container_of(c, sd_bus_slot, reply_callback); - bus->current = m; bus->iteration_counter++; - r = c->callback(bus, m, c->userdata, &error_buffer); + r = c->callback(bus, m, bus->current_slot->userdata, &error_buffer); r = bus_maybe_reply_error(m, r, &error_buffer); - free(c); + + bus->current_slot = NULL; goto finish; } @@ -2572,7 +2558,7 @@ static int process_closing(sd_bus *bus, sd_bus_message **ret) { sd_bus_close(bus); - bus->current = m; + bus->current_message = m; bus->iteration_counter++; r = process_filter(bus, m); @@ -2591,7 +2577,8 @@ static int process_closing(sd_bus *bus, sd_bus_message **ret) { r = 1; finish: - bus->current = NULL; + bus->current_message = NULL; + return r; } @@ -2608,7 +2595,8 @@ static int bus_process_internal(sd_bus *bus, bool hint_priority, int64_t priorit assert_return(!bus_pid_changed(bus), -ECHILD); /* We don't allow recursively invoking sd_bus_process(). */ - assert_return(!bus->current, -EBUSY); + assert_return(!bus->current_message, -EBUSY); + assert(!bus->current_slot); switch (bus->state) { @@ -2785,57 +2773,43 @@ _public_ int sd_bus_flush(sd_bus *bus) { } } -_public_ int sd_bus_add_filter(sd_bus *bus, - sd_bus_message_handler_t callback, - void *userdata) { +_public_ int sd_bus_add_filter( + sd_bus *bus, + sd_bus_slot **slot, + sd_bus_message_handler_t callback, + void *userdata) { - struct filter_callback *f; + sd_bus_slot *s; assert_return(bus, -EINVAL); assert_return(callback, -EINVAL); assert_return(!bus_pid_changed(bus), -ECHILD); - f = new0(struct filter_callback, 1); - if (!f) + s = bus_slot_allocate(bus, !slot, BUS_FILTER_CALLBACK, sizeof(struct filter_callback), userdata); + if (!s) return -ENOMEM; - f->callback = callback; - f->userdata = userdata; - bus->filter_callbacks_modified = true; - LIST_PREPEND(callbacks, bus->filter_callbacks, f); - return 0; -} + s->filter_callback.callback = callback; -_public_ int sd_bus_remove_filter(sd_bus *bus, - sd_bus_message_handler_t callback, - void *userdata) { - - struct filter_callback *f; - - assert_return(bus, -EINVAL); - assert_return(callback, -EINVAL); - assert_return(!bus_pid_changed(bus), -ECHILD); + bus->filter_callbacks_modified = true; + LIST_PREPEND(callbacks, bus->filter_callbacks, &s->filter_callback); - LIST_FOREACH(callbacks, f, bus->filter_callbacks) { - if (f->callback == callback && f->userdata == userdata) { - bus->filter_callbacks_modified = true; - LIST_REMOVE(callbacks, bus->filter_callbacks, f); - free(f); - return 1; - } - } + if (slot) + *slot = s; return 0; } -_public_ int sd_bus_add_match(sd_bus *bus, - const char *match, - sd_bus_message_handler_t callback, - void *userdata) { +_public_ int sd_bus_add_match( + sd_bus *bus, + sd_bus_slot **slot, + const char *match, + sd_bus_message_handler_t callback, + void *userdata) { struct bus_match_component *components = NULL; unsigned n_components = 0; - uint64_t cookie = 0; + sd_bus_slot *s; int r = 0; assert_return(bus, -EINVAL); @@ -2846,35 +2820,60 @@ _public_ int sd_bus_add_match(sd_bus *bus, if (r < 0) goto finish; + s = bus_slot_allocate(bus, !slot, BUS_MATCH_CALLBACK, sizeof(struct match_callback), userdata); + if (!s) { + r = -ENOMEM; + goto finish; + } + + s->match_callback.callback = callback; + s->match_callback.cookie = ++bus->match_cookie; + if (bus->bus_client) { - cookie = ++bus->match_cookie; - r = bus_add_match_internal(bus, match, components, n_components, cookie); + if (!bus->is_kernel) { + /* When this is not a kernel transport, we + * store the original match string, so that we + * can use it to remove the match again */ + + s->match_callback.match_string = strdup(match); + if (!s->match_callback.match_string) { + r = -ENOMEM; + goto finish; + } + } + + r = bus_add_match_internal(bus, s->match_callback.match_string, components, n_components, s->match_callback.cookie); if (r < 0) goto finish; } bus->match_callbacks_modified = true; - r = bus_match_add(&bus->match_callbacks, components, n_components, callback, userdata, cookie, NULL); - if (r < 0) { - if (bus->bus_client) - bus_remove_match_internal(bus, match, cookie); - } + r = bus_match_add(&bus->match_callbacks, components, n_components, &s->match_callback); + if (r < 0) + goto finish; + + if (slot) + *slot = s; + s = NULL; finish: bus_match_parse_free(components, n_components); + sd_bus_slot_unref(s); + return r; } -_public_ int sd_bus_remove_match(sd_bus *bus, - const char *match, - sd_bus_message_handler_t callback, - void *userdata) { +int bus_remove_match_by_string( + sd_bus *bus, + const char *match, + sd_bus_message_handler_t callback, + void *userdata) { struct bus_match_component *components = NULL; unsigned n_components = 0; - int r = 0, q = 0; - uint64_t cookie = 0; + struct match_callback *c; + int r = 0; assert_return(bus, -EINVAL); assert_return(match, -EINVAL); @@ -2882,17 +2881,18 @@ _public_ int sd_bus_remove_match(sd_bus *bus, r = bus_match_parse(match, &components, &n_components); if (r < 0) - return r; + goto finish; - bus->match_callbacks_modified = true; - r = bus_match_remove(&bus->match_callbacks, components, n_components, callback, userdata, &cookie); + r = bus_match_find(&bus->match_callbacks, components, n_components, NULL, NULL, &c); + if (r <= 0) + goto finish; - if (bus->bus_client) - q = bus_remove_match_internal(bus, match, cookie); + sd_bus_slot_unref(container_of(c, sd_bus_slot, match_callback)); +finish: bus_match_parse_free(components, n_components); - return r < 0 ? r : q; + return r; } bool bus_pid_changed(sd_bus *bus) { @@ -3116,10 +3116,16 @@ _public_ sd_event* sd_bus_get_event(sd_bus *bus) { return bus->event; } -_public_ sd_bus_message* sd_bus_get_current(sd_bus *bus) { +_public_ sd_bus_message* sd_bus_get_current_message(sd_bus *bus) { + assert_return(bus, NULL); + + return bus->current_message; +} + +_public_ sd_bus_slot* sd_bus_get_current_slot(sd_bus *bus) { assert_return(bus, NULL); - return bus->current; + return bus->current_slot; } static int bus_default(int (*bus_open)(sd_bus **), sd_bus **default_bus, sd_bus **ret) { diff --git a/src/libsystemd/sd-bus/test-bus-chat.c b/src/libsystemd/sd-bus/test-bus-chat.c index c0abc7a697..c9eb69843d 100644 --- a/src/libsystemd/sd-bus/test-bus-chat.c +++ b/src/libsystemd/sd-bus/test-bus-chat.c @@ -100,19 +100,19 @@ static int server_init(sd_bus **_bus) { goto fail; } - r = sd_bus_add_fallback(bus, "/foo/bar", object_callback, NULL); + r = sd_bus_add_fallback(bus, NULL, "/foo/bar", object_callback, NULL); if (r < 0) { log_error("Failed to add object: %s", strerror(-r)); goto fail; } - r = sd_bus_add_match(bus, "type='signal',interface='foo.bar',member='Notify'", match_callback, NULL); + r = sd_bus_add_match(bus, NULL, "type='signal',interface='foo.bar',member='Notify'", match_callback, NULL); if (r < 0) { log_error("Failed to add match: %s", strerror(-r)); goto fail; } - r = sd_bus_add_match(bus, "type='signal',interface='org.freedesktop.DBus',member='NameOwnerChanged'", match_callback, NULL); + r = sd_bus_add_match(bus, NULL, "type='signal',interface='org.freedesktop.DBus',member='NameOwnerChanged'", match_callback, NULL); if (r < 0) { log_error("Failed to add match: %s", strerror(-r)); goto fail; @@ -490,7 +490,7 @@ static void* client2(void*p) { goto finish; } - r = sd_bus_call_async(bus, m, quit_callback, &quit, 200 * USEC_PER_MSEC, NULL); + r = sd_bus_call_async(bus, NULL, m, quit_callback, &quit, 200 * USEC_PER_MSEC); if (r < 0) { log_info("Failed to issue method call: %s", bus_error_message(&error, -r)); goto finish; diff --git a/src/libsystemd/sd-bus/test-bus-kernel-bloom.c b/src/libsystemd/sd-bus/test-bus-kernel-bloom.c index 0ecad18f45..5ee6eea0e8 100644 --- a/src/libsystemd/sd-bus/test-bus-kernel-bloom.c +++ b/src/libsystemd/sd-bus/test-bus-kernel-bloom.c @@ -72,7 +72,7 @@ static void test_one( assert_se(r >= 0); log_debug("match"); - r = sd_bus_add_match(b, match, NULL, NULL); + r = sd_bus_add_match(b, NULL, match, NULL, NULL); assert_se(r >= 0); log_debug("signal"); diff --git a/src/libsystemd/sd-bus/test-bus-kernel.c b/src/libsystemd/sd-bus/test-bus-kernel.c index 34d000f1c6..7bb8b0a540 100644 --- a/src/libsystemd/sd-bus/test-bus-kernel.c +++ b/src/libsystemd/sd-bus/test-bus-kernel.c @@ -101,7 +101,7 @@ int main(int argc, char *argv[]) { assert_se(sd_bus_error_has_name(&error, SD_BUS_ERROR_SERVICE_UNKNOWN)); assert_se(r == -EHOSTUNREACH); - r = sd_bus_add_match(b, "interface='waldo.com',member='Piep'", NULL, NULL); + r = sd_bus_add_match(b, NULL, "interface='waldo.com',member='Piep'", NULL, NULL); assert_se(r >= 0); r = sd_bus_emit_signal(a, "/foo/bar/waldo", "waldo.com", "Piep", "sss", "I am a string", "/this/is/a/path", "and.this.a.domain.name"); diff --git a/src/libsystemd/sd-bus/test-bus-match.c b/src/libsystemd/sd-bus/test-bus-match.c index c561be2a65..a62de502f9 100644 --- a/src/libsystemd/sd-bus/test-bus-match.c +++ b/src/libsystemd/sd-bus/test-bus-match.c @@ -28,6 +28,7 @@ #include "bus-match.h" #include "bus-message.h" #include "bus-util.h" +#include "bus-slot.h" static bool mask[32]; @@ -56,31 +57,23 @@ static bool mask_contains(unsigned a[], unsigned n) { return true; } -static int match_add(struct bus_match_node *root, const char *match, int value) { +static int match_add(sd_bus_slot *slots, struct bus_match_node *root, const char *match, int value) { struct bus_match_component *components = NULL; unsigned n_components = 0; + sd_bus_slot *s; int r; - r = bus_match_parse(match, &components, &n_components); - if (r < 0) - return r; - - r = bus_match_add(root, components, n_components, filter, INT_TO_PTR(value), 0, NULL); - bus_match_parse_free(components, n_components); - - return r; -} - -static int match_remove(struct bus_match_node *root, const char *match, int value) { - struct bus_match_component *components = NULL; - unsigned n_components = 0; - int r; + s = slots + value; + zero(*s); r = bus_match_parse(match, &components, &n_components); if (r < 0) return r; - r = bus_match_remove(root, components, n_components, filter, INT_TO_PTR(value), 0); + s->userdata = INT_TO_PTR(value); + s->match_callback.callback = filter; + + r = bus_match_add(root, components, n_components, &s->match_callback); bus_match_parse_free(components, n_components); return r; @@ -90,24 +83,25 @@ int main(int argc, char *argv[]) { struct bus_match_node root; _cleanup_bus_message_unref_ sd_bus_message *m = NULL; enum bus_match_node_type i; + sd_bus_slot slots[15]; zero(root); root.type = BUS_MATCH_ROOT; - assert_se(match_add(&root, "arg2='wal\\'do',sender='foo',type='signal',interface='bar.x',", 1) >= 0); - assert_se(match_add(&root, "arg2='wal\\'do2',sender='foo',type='signal',interface='bar.x',", 2) >= 0); - assert_se(match_add(&root, "arg3='test',sender='foo',type='signal',interface='bar.x',", 3) >= 0); - assert_se(match_add(&root, "arg3='test',sender='foo',type='method_call',interface='bar.x',", 4) >= 0); - assert_se(match_add(&root, "", 5) >= 0); - assert_se(match_add(&root, "interface='quux.x'", 6) >= 0); - assert_se(match_add(&root, "interface='bar.x'", 7) >= 0); - assert_se(match_add(&root, "member='waldo',path='/foo/bar'", 8) >= 0); - assert_se(match_add(&root, "path='/foo/bar'", 9) >= 0); - assert_se(match_add(&root, "path_namespace='/foo'", 10) >= 0); - assert_se(match_add(&root, "path_namespace='/foo/quux'", 11) >= 0); - assert_se(match_add(&root, "arg1='two'", 12) >= 0); - assert_se(match_add(&root, "member='waldo',arg2path='/prefix/'", 13) >= 0); - assert_se(match_add(&root, "member=waldo,path='/foo/bar',arg3namespace='prefix'", 14) >= 0); + assert_se(match_add(slots, &root, "arg2='wal\\'do',sender='foo',type='signal',interface='bar.x',", 1) >= 0); + assert_se(match_add(slots, &root, "arg2='wal\\'do2',sender='foo',type='signal',interface='bar.x',", 2) >= 0); + assert_se(match_add(slots, &root, "arg3='test',sender='foo',type='signal',interface='bar.x',", 3) >= 0); + assert_se(match_add(slots, &root, "arg3='test',sender='foo',type='method_call',interface='bar.x',", 4) >= 0); + assert_se(match_add(slots, &root, "", 5) >= 0); + assert_se(match_add(slots, &root, "interface='quux.x'", 6) >= 0); + assert_se(match_add(slots, &root, "interface='bar.x'", 7) >= 0); + assert_se(match_add(slots, &root, "member='waldo',path='/foo/bar'", 8) >= 0); + assert_se(match_add(slots, &root, "path='/foo/bar'", 9) >= 0); + assert_se(match_add(slots, &root, "path_namespace='/foo'", 10) >= 0); + assert_se(match_add(slots, &root, "path_namespace='/foo/quux'", 11) >= 0); + assert_se(match_add(slots, &root, "arg1='two'", 12) >= 0); + assert_se(match_add(slots, &root, "member='waldo',arg2path='/prefix/'", 13) >= 0); + assert_se(match_add(slots, &root, "member=waldo,path='/foo/bar',arg3namespace='prefix'", 14) >= 0); bus_match_dump(&root, 0); @@ -119,9 +113,8 @@ int main(int argc, char *argv[]) { assert_se(bus_match_run(NULL, &root, m) == 0); assert_se(mask_contains((unsigned[]) { 9, 8, 7, 5, 10, 12, 13, 14 }, 8)); - assert_se(match_remove(&root, "member='waldo',path='/foo/bar'", 8) > 0); - assert_se(match_remove(&root, "arg2path='/prefix/',member='waldo'", 13) > 0); - assert_se(match_remove(&root, "interface='bar.xx'", 7) == 0); + assert_se(bus_match_remove(&root, &slots[8].match_callback) >= 0); + assert_se(bus_match_remove(&root, &slots[13].match_callback) >= 0); bus_match_dump(&root, 0); diff --git a/src/libsystemd/sd-bus/test-bus-objects.c b/src/libsystemd/sd-bus/test-bus-objects.c index e2423c7f67..e7a445f3cb 100644 --- a/src/libsystemd/sd-bus/test-bus-objects.c +++ b/src/libsystemd/sd-bus/test-bus-objects.c @@ -200,7 +200,7 @@ static const sd_bus_vtable vtable2[] = { SD_BUS_VTABLE_END }; -static int enumerator_callback(sd_bus *b, const char *path, void *userdata, char ***nodes, sd_bus_error *error) { +static int enumerator_callback(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) { if (object_path_startswith("/value", path)) assert_se(*nodes = strv_new("/value/a", "/value/b", "/value/c", NULL)); @@ -222,11 +222,11 @@ static void *server(void *p) { assert_se(sd_bus_set_fd(bus, c->fds[0], c->fds[0]) >= 0); assert_se(sd_bus_set_server(bus, 1, id) >= 0); - assert_se(sd_bus_add_object_vtable(bus, "/foo", "org.freedesktop.systemd.test", vtable, c) >= 0); - assert_se(sd_bus_add_object_vtable(bus, "/foo", "org.freedesktop.systemd.test2", vtable, c) >= 0); - assert_se(sd_bus_add_fallback_vtable(bus, "/value", "org.freedesktop.systemd.ValueTest", vtable2, NULL, UINT_TO_PTR(20)) >= 0); - assert_se(sd_bus_add_node_enumerator(bus, "/value", enumerator_callback, NULL) >= 0); - assert_se(sd_bus_add_object_manager(bus, "/value") >= 0); + assert_se(sd_bus_add_object_vtable(bus, NULL, "/foo", "org.freedesktop.systemd.test", vtable, c) >= 0); + assert_se(sd_bus_add_object_vtable(bus, NULL, "/foo", "org.freedesktop.systemd.test2", vtable, c) >= 0); + assert_se(sd_bus_add_fallback_vtable(bus, NULL, "/value", "org.freedesktop.systemd.ValueTest", vtable2, NULL, UINT_TO_PTR(20)) >= 0); + assert_se(sd_bus_add_node_enumerator(bus, NULL, "/value", enumerator_callback, NULL) >= 0); + assert_se(sd_bus_add_object_manager(bus, NULL, "/value") >= 0); assert_se(sd_bus_start(bus) >= 0); diff --git a/src/locale/localed.c b/src/locale/localed.c index de6e3b2f84..e3061c8d5e 100644 --- a/src/locale/localed.c +++ b/src/locale/localed.c @@ -1088,7 +1088,7 @@ static int connect_bus(Context *c, sd_event *event, sd_bus **_bus) { return r; } - r = sd_bus_add_object_vtable(bus, "/org/freedesktop/locale1", "org.freedesktop.locale1", locale_vtable, c); + r = sd_bus_add_object_vtable(bus, NULL, "/org/freedesktop/locale1", "org.freedesktop.locale1", locale_vtable, c); if (r < 0) { log_error("Failed to register object: %s", strerror(-r)); return r; diff --git a/src/login/logind-seat-dbus.c b/src/login/logind-seat-dbus.c index 82323d6b87..1a2f09c615 100644 --- a/src/login/logind-seat-dbus.c +++ b/src/login/logind-seat-dbus.c @@ -329,7 +329,7 @@ int seat_object_find(sd_bus *bus, const char *path, const char *interface, void Session *session; pid_t pid; - message = sd_bus_get_current(bus); + message = sd_bus_get_current_message(bus); if (!message) return 0; diff --git a/src/login/logind-session-dbus.c b/src/login/logind-session-dbus.c index ffdc5582dc..7d81500426 100644 --- a/src/login/logind-session-dbus.c +++ b/src/login/logind-session-dbus.c @@ -493,7 +493,7 @@ int session_object_find(sd_bus *bus, const char *path, const char *interface, vo sd_bus_message *message; pid_t pid; - message = sd_bus_get_current(bus); + message = sd_bus_get_current_message(bus); if (!message) return 0; diff --git a/src/login/logind-user-dbus.c b/src/login/logind-user-dbus.c index b5d27e74de..4f1a079ecd 100644 --- a/src/login/logind-user-dbus.c +++ b/src/login/logind-user-dbus.c @@ -250,7 +250,7 @@ int user_object_find(sd_bus *bus, const char *path, const char *interface, void sd_bus_message *message; pid_t pid; - message = sd_bus_get_current(bus); + message = sd_bus_get_current_message(bus); if (!message) return 0; diff --git a/src/login/logind.c b/src/login/logind.c index 86ce7df5d6..686506cc65 100644 --- a/src/login/logind.c +++ b/src/login/logind.c @@ -586,49 +586,50 @@ static int manager_connect_bus(Manager *m) { return r; } - r = sd_bus_add_object_vtable(m->bus, "/org/freedesktop/login1", "org.freedesktop.login1.Manager", manager_vtable, m); + r = sd_bus_add_object_vtable(m->bus, NULL, "/org/freedesktop/login1", "org.freedesktop.login1.Manager", manager_vtable, m); if (r < 0) { log_error("Failed to add manager object vtable: %s", strerror(-r)); return r; } - r = sd_bus_add_fallback_vtable(m->bus, "/org/freedesktop/login1/seat", "org.freedesktop.login1.Seat", seat_vtable, seat_object_find, m); + r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/login1/seat", "org.freedesktop.login1.Seat", seat_vtable, seat_object_find, m); if (r < 0) { log_error("Failed to add seat object vtable: %s", strerror(-r)); return r; } - r = sd_bus_add_node_enumerator(m->bus, "/org/freedesktop/login1/seat", seat_node_enumerator, m); + r = sd_bus_add_node_enumerator(m->bus, NULL, "/org/freedesktop/login1/seat", seat_node_enumerator, m); if (r < 0) { log_error("Failed to add seat enumerator: %s", strerror(-r)); return r; } - r = sd_bus_add_fallback_vtable(m->bus, "/org/freedesktop/login1/session", "org.freedesktop.login1.Session", session_vtable, session_object_find, m); + r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/login1/session", "org.freedesktop.login1.Session", session_vtable, session_object_find, m); if (r < 0) { log_error("Failed to add session object vtable: %s", strerror(-r)); return r; } - r = sd_bus_add_node_enumerator(m->bus, "/org/freedesktop/login1/session", session_node_enumerator, m); + r = sd_bus_add_node_enumerator(m->bus, NULL, "/org/freedesktop/login1/session", session_node_enumerator, m); if (r < 0) { log_error("Failed to add session enumerator: %s", strerror(-r)); return r; } - r = sd_bus_add_fallback_vtable(m->bus, "/org/freedesktop/login1/user", "org.freedesktop.login1.User", user_vtable, user_object_find, m); + r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/login1/user", "org.freedesktop.login1.User", user_vtable, user_object_find, m); if (r < 0) { log_error("Failed to add user object vtable: %s", strerror(-r)); return r; } - r = sd_bus_add_node_enumerator(m->bus, "/org/freedesktop/login1/user", user_node_enumerator, m); + r = sd_bus_add_node_enumerator(m->bus, NULL, "/org/freedesktop/login1/user", user_node_enumerator, m); if (r < 0) { log_error("Failed to add user enumerator: %s", strerror(-r)); return r; } r = sd_bus_add_match(m->bus, + NULL, "type='signal'," "sender='org.freedesktop.DBus'," "interface='org.freedesktop.DBus'," @@ -641,6 +642,7 @@ static int manager_connect_bus(Manager *m) { } r = sd_bus_add_match(m->bus, + NULL, "type='signal'," "sender='org.freedesktop.systemd1'," "interface='org.freedesktop.systemd1.Manager'," @@ -653,6 +655,7 @@ static int manager_connect_bus(Manager *m) { } r = sd_bus_add_match(m->bus, + NULL, "type='signal'," "sender='org.freedesktop.systemd1'," "interface='org.freedesktop.systemd1.Manager'," @@ -665,6 +668,7 @@ static int manager_connect_bus(Manager *m) { } r = sd_bus_add_match(m->bus, + NULL, "type='signal'," "sender='org.freedesktop.systemd1'," "interface='org.freedesktop.DBus.Properties'," @@ -676,6 +680,7 @@ static int manager_connect_bus(Manager *m) { } r = sd_bus_add_match(m->bus, + NULL, "type='signal'," "sender='org.freedesktop.systemd1'," "interface='org.freedesktop.systemd1.Manager'," diff --git a/src/machine/machine-dbus.c b/src/machine/machine-dbus.c index 920c9956ae..83ef82d2e0 100644 --- a/src/machine/machine-dbus.c +++ b/src/machine/machine-dbus.c @@ -160,7 +160,7 @@ int machine_object_find(sd_bus *bus, const char *path, const char *interface, vo sd_bus_message *message; pid_t pid; - message = sd_bus_get_current(bus); + message = sd_bus_get_current_message(bus); if (!message) return 0; diff --git a/src/machine/machined.c b/src/machine/machined.c index 20e6f7cd63..45768d2e97 100644 --- a/src/machine/machined.c +++ b/src/machine/machined.c @@ -141,25 +141,26 @@ static int manager_connect_bus(Manager *m) { return r; } - r = sd_bus_add_object_vtable(m->bus, "/org/freedesktop/machine1", "org.freedesktop.machine1.Manager", manager_vtable, m); + r = sd_bus_add_object_vtable(m->bus, NULL, "/org/freedesktop/machine1", "org.freedesktop.machine1.Manager", manager_vtable, m); if (r < 0) { log_error("Failed to add manager object vtable: %s", strerror(-r)); return r; } - r = sd_bus_add_fallback_vtable(m->bus, "/org/freedesktop/machine1/machine", "org.freedesktop.machine1.Machine", machine_vtable, machine_object_find, m); + r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/machine1/machine", "org.freedesktop.machine1.Machine", machine_vtable, machine_object_find, m); if (r < 0) { log_error("Failed to add machine object vtable: %s", strerror(-r)); return r; } - r = sd_bus_add_node_enumerator(m->bus, "/org/freedesktop/machine1/machine", machine_node_enumerator, m); + r = sd_bus_add_node_enumerator(m->bus, NULL, "/org/freedesktop/machine1/machine", machine_node_enumerator, m); if (r < 0) { log_error("Failed to add machine enumerator: %s", strerror(-r)); return r; } r = sd_bus_add_match(m->bus, + NULL, "type='signal'," "sender='org.freedesktop.systemd1'," "interface='org.freedesktop.systemd1.Manager'," @@ -173,6 +174,7 @@ static int manager_connect_bus(Manager *m) { } r = sd_bus_add_match(m->bus, + NULL, "type='signal'," "sender='org.freedesktop.systemd1'," "interface='org.freedesktop.systemd1.Manager'," @@ -186,6 +188,7 @@ static int manager_connect_bus(Manager *m) { } r = sd_bus_add_match(m->bus, + NULL, "type='signal'," "sender='org.freedesktop.systemd1'," "interface='org.freedesktop.DBus.Properties'," @@ -198,6 +201,7 @@ static int manager_connect_bus(Manager *m) { } r = sd_bus_add_match(m->bus, + NULL, "type='signal'," "sender='org.freedesktop.systemd1'," "interface='org.freedesktop.systemd1.Manager'," diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 77c505fc78..37a572dc0f 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -684,7 +684,7 @@ static int link_set_hostname(Link *link, const char *hostname) { if (r < 0) return r; - r = sd_bus_call_async(link->manager->bus, m, set_hostname_handler, link, 0, NULL); + r = sd_bus_call_async(link->manager->bus, NULL, m, set_hostname_handler, link, 0); if (r < 0) log_error_link(link, "Could not set transient hostname: %s", strerror(-r)); diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index e1e4640ae8..91d8032945 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -2305,6 +2305,7 @@ static int enable_wait_for_jobs(sd_bus *bus) { r = sd_bus_add_match( bus, + NULL, "type='signal'," "sender='org.freedesktop.systemd1'," "interface='org.freedesktop.systemd1.Manager'," @@ -2364,13 +2365,14 @@ static int check_wait_response(WaitData *d) { } static int wait_for_jobs(sd_bus *bus, Set *s) { + _cleanup_bus_slot_unref_ sd_bus_slot *slot = NULL; WaitData d = { .set = s }; int r = 0, q; assert(bus); assert(s); - q = sd_bus_add_filter(bus, wait_filter, &d); + q = sd_bus_add_filter(bus, &slot, wait_filter, &d); if (q < 0) return log_oom(); @@ -2398,10 +2400,6 @@ static int wait_for_jobs(sd_bus *bus, Set *s) { d.result = NULL; } - q = sd_bus_remove_filter(bus, wait_filter, &d); - if (q < 0 && r == 0) - r = q; - return r; } diff --git a/src/systemd/sd-bus.h b/src/systemd/sd-bus.h index c6787ca809..79566d2109 100644 --- a/src/systemd/sd-bus.h +++ b/src/systemd/sd-bus.h @@ -37,6 +37,7 @@ _SD_BEGIN_DECLARATIONS; typedef struct sd_bus sd_bus; typedef struct sd_bus_message sd_bus_message; +typedef struct sd_bus_slot sd_bus_slot; typedef struct sd_bus_creds sd_bus_creds; typedef struct sd_bus_track sd_bus_track; @@ -138,8 +139,7 @@ int sd_bus_get_tid(sd_bus *bus, pid_t *tid); int sd_bus_send(sd_bus *bus, sd_bus_message *m, uint64_t *cookie); int sd_bus_send_to(sd_bus *bus, sd_bus_message *m, const char *destination, uint64_t *cookie); int sd_bus_call(sd_bus *bus, sd_bus_message *m, uint64_t usec, sd_bus_error *ret_error, sd_bus_message **reply); -int sd_bus_call_async(sd_bus *bus, sd_bus_message *m, sd_bus_message_handler_t callback, void *userdata, uint64_t usec, uint64_t *cookie); -int sd_bus_call_async_cancel(sd_bus *bus, uint64_t cookie); +int sd_bus_call_async(sd_bus *bus, sd_bus_slot **slot, sd_bus_message *m, sd_bus_message_handler_t callback, void *userdata, uint64_t usec); int sd_bus_get_fd(sd_bus *bus); int sd_bus_get_events(sd_bus *bus); @@ -148,35 +148,33 @@ int sd_bus_process(sd_bus *bus, sd_bus_message **r); int sd_bus_process_priority(sd_bus *bus, int64_t max_priority, sd_bus_message **r); int sd_bus_wait(sd_bus *bus, uint64_t timeout_usec); int sd_bus_flush(sd_bus *bus); -sd_bus_message* sd_bus_get_current(sd_bus *bus); +sd_bus_message* sd_bus_get_current_message(sd_bus *bus); +sd_bus_slot* sd_bus_get_current_slot(sd_bus *bus); int sd_bus_attach_event(sd_bus *bus, sd_event *e, int priority); int sd_bus_detach_event(sd_bus *bus); sd_event *sd_bus_get_event(sd_bus *bus); -int sd_bus_add_filter(sd_bus *bus, sd_bus_message_handler_t callback, void *userdata); -int sd_bus_remove_filter(sd_bus *bus, sd_bus_message_handler_t callback, void *userdata); +int sd_bus_add_filter(sd_bus *bus, sd_bus_slot **slot, sd_bus_message_handler_t callback, void *userdata); +int sd_bus_add_match(sd_bus *bus, sd_bus_slot **slot, const char *match, sd_bus_message_handler_t callback, void *userdata); +int sd_bus_add_object(sd_bus *bus, sd_bus_slot **slot, const char *path, sd_bus_message_handler_t callback, void *userdata); +int sd_bus_add_fallback(sd_bus *bus, sd_bus_slot **slot, const char *prefix, sd_bus_message_handler_t callback, void *userdata); +int sd_bus_add_object_vtable(sd_bus *bus, sd_bus_slot **slot, const char *path, const char *interface, const sd_bus_vtable *vtable, void *userdata); +int sd_bus_add_fallback_vtable(sd_bus *bus, sd_bus_slot **slot, const char *prefix, const char *interface, const sd_bus_vtable *vtable, sd_bus_object_find_t find, void *userdata); +int sd_bus_add_node_enumerator(sd_bus *bus, sd_bus_slot **slot, const char *path, sd_bus_node_enumerator_t callback, void *userdata); +int sd_bus_add_object_manager(sd_bus *bus, sd_bus_slot **slot, const char *path); -int sd_bus_add_match(sd_bus *bus, const char *match, sd_bus_message_handler_t callback, void *userdata); -int sd_bus_remove_match(sd_bus *bus, const char *match, sd_bus_message_handler_t callback, void *userdata); +/* Slot object */ -int sd_bus_add_object(sd_bus *bus, const char *path, sd_bus_message_handler_t callback, void *userdata); -int sd_bus_remove_object(sd_bus *bus, const char *path, sd_bus_message_handler_t callback, void *userdata); +sd_bus_slot* sd_bus_slot_ref(sd_bus_slot *slot); +sd_bus_slot* sd_bus_slot_unref(sd_bus_slot *slot); -int sd_bus_add_fallback(sd_bus *bus, const char *prefix, sd_bus_message_handler_t callback, void *userdata); -int sd_bus_remove_fallback(sd_bus *bus, const char *prefix, sd_bus_message_handler_t callback, void *userdata); +sd_bus* sd_bus_slot_get_bus(sd_bus_slot *slot); -int sd_bus_add_object_vtable(sd_bus *bus, const char *path, const char *interface, const sd_bus_vtable *vtable, void *userdata); -int sd_bus_remove_object_vtable(sd_bus *bus, const char *path, const char *interface, const sd_bus_vtable *vtable, void *userdata); +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_add_fallback_vtable(sd_bus *bus, const char *path, const char *interface, const sd_bus_vtable *vtable, sd_bus_object_find_t find, void *userdata); -int sd_bus_remove_fallback_vtable(sd_bus *bus, const char *path, const char *interface, const sd_bus_vtable *vtable, sd_bus_object_find_t find, void *userdata); - -int sd_bus_add_node_enumerator(sd_bus *bus, const char *path, sd_bus_node_enumerator_t callback, void *userdata); -int sd_bus_remove_node_enumerator(sd_bus *bus, const char *path, sd_bus_node_enumerator_t callback, void *userdata); - -int sd_bus_add_object_manager(sd_bus *bus, const char *path); -int sd_bus_remove_object_manager(sd_bus *bus, const char *path); +sd_bus_message* sd_bus_slot_get_current_message(sd_bus_slot *slot); /* Message object */ diff --git a/src/timedate/timedated.c b/src/timedate/timedated.c index 3895e321c2..1b09380094 100644 --- a/src/timedate/timedated.c +++ b/src/timedate/timedated.c @@ -784,7 +784,7 @@ static int connect_bus(Context *c, sd_event *event, sd_bus **_bus) { return r; } - r = sd_bus_add_object_vtable(bus, "/org/freedesktop/timedate1", "org.freedesktop.timedate1", timedate_vtable, c); + r = sd_bus_add_object_vtable(bus, NULL, "/org/freedesktop/timedate1", "org.freedesktop.timedate1", timedate_vtable, c); if (r < 0) { log_error("Failed to register object: %s", strerror(-r)); return r; |