X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Flibsystemd-bus%2Fsd-bus.c;h=7f3ecbf8047eb3d815b8646ae7ccb66e608aee5b;hb=843f737ade9c73609a2280dd3dd16e18222a5dcb;hp=76a27ec3c7bc3c496e98b12ce26e43d2d278f80f;hpb=821e0756c62d705252ab13d24af941578c0b9642;p=elogind.git diff --git a/src/libsystemd-bus/sd-bus.c b/src/libsystemd-bus/sd-bus.c index 76a27ec3c..7f3ecbf80 100644 --- a/src/libsystemd-bus/sd-bus.c +++ b/src/libsystemd-bus/sd-bus.c @@ -34,6 +34,7 @@ #include "strv.h" #include "set.h" #include "missing.h" +#include "def.h" #include "sd-bus.h" #include "bus-internal.h" @@ -141,6 +142,8 @@ static void bus_free(sd_bus *b) { free(b->address); free(b->kernel); free(b->machine); + free(b->fake_label); + free(b->cgroup_root); free(b->exec_path); strv_free(b->exec_argv); @@ -374,14 +377,14 @@ static int bus_send_hello(sd_bus *bus) { r = sd_bus_message_new_method_call( bus, "org.freedesktop.DBus", - "/", + "/org/freedesktop/DBus", "org.freedesktop.DBus", "Hello", &m); if (r < 0) return r; - return sd_bus_call_async(bus, m, hello_callback, NULL, 0, &bus->hello_serial); + return sd_bus_call_async(bus, m, hello_callback, NULL, 0, &bus->hello_cookie); } int bus_start_running(sd_bus *bus) { @@ -1045,12 +1048,7 @@ _public_ int sd_bus_open_system(sd_bus **ret) { if (e) r = sd_bus_set_address(b, e); else -#ifdef ENABLE_KDBUS - r = sd_bus_set_address(b, "kernel:path=/dev/kdbus/0-system/bus;unix:path=/run/dbus/system_bus_socket"); -#else - r = sd_bus_set_address(b, "unix:path=/run/dbus/system_bus_socket"); -#endif - + r = sd_bus_set_address(b, DEFAULT_SYSTEM_BUS_PATH); if (r < 0) goto fail; @@ -1101,13 +1099,13 @@ _public_ int sd_bus_open_user(sd_bus **ret) { } #ifdef ENABLE_KDBUS - asprintf(&b->address, "kernel:path=/dev/kdbus/%lu-user/bus;unix:path=%s/bus", (unsigned long) getuid(), ee); + asprintf(&b->address, KERNEL_USER_BUS_FMT ";" UNIX_USER_BUS_FMT, (unsigned long) getuid(), ee); #else - b->address = strjoin("unix:path=", ee, "/bus", NULL); + asprintf(&b->address, UNIX_USER_BUS_FMT, ee); #endif } else { #ifdef ENABLE_KDBUS - asprintf(&b->address, "kernel:path=/dev/kdbus/%lu-user/bus", (unsigned long) getuid()); + asprintf(&b->address, KERNEL_USER_BUS_FMT, (unsigned long) getuid()); #else return -ECONNREFUSED; #endif @@ -1236,7 +1234,7 @@ _public_ void sd_bus_close(sd_bus *bus) { /* We'll leave the fd open in case this is a kernel bus, since * there might still be memblocks around that reference this - * bus, and they might need to invoke the * KDBUS_CMD_FREE + * bus, and they might need to invoke the KDBUS_CMD_FREE * ioctl on the fd when they are freed. */ } @@ -1319,26 +1317,30 @@ static int bus_seal_message(sd_bus *b, sd_bus_message *m, usec_t timeout) { assert(b); assert(m); - if (b->message_version != 0 && - m->header->version != b->message_version) - return -EPERM; - - if (b->message_endian != 0 && - m->header->endian != b->message_endian) - return -EPERM; - if (m->sealed) { /* If we copy the same message to multiple - * destinations, avoid using the same serial + * destinations, avoid using the same cookie * numbers. */ - b->serial = MAX(b->serial, BUS_MESSAGE_SERIAL(m)); + b->cookie = MAX(b->cookie, BUS_MESSAGE_COOKIE(m)); return 0; } if (timeout == 0) timeout = BUS_DEFAULT_TIMEOUT; - return bus_message_seal(m, ++b->serial, timeout); + return bus_message_seal(m, ++b->cookie, timeout); +} + +static int bus_remarshal_message(sd_bus *b, sd_bus_message **m) { + assert(b); + + /* Do packet version and endianess already match? */ + if ((b->message_version == 0 || b->message_version == (*m)->header->version) && + (b->message_endian == 0 || b->message_endian == (*m)->header->endian)) + return 0; + + /* No? Then remarshal! */ + return bus_message_remarshal(b, m); } int bus_seal_synthetic_message(sd_bus *b, sd_bus_message *m) { @@ -1356,14 +1358,33 @@ int bus_seal_synthetic_message(sd_bus *b, sd_bus_message *m) { return bus_message_seal(m, 0xFFFFFFFFULL, 0); } -static int bus_write_message(sd_bus *bus, sd_bus_message *message, size_t *idx) { +static int bus_write_message(sd_bus *bus, sd_bus_message *m, size_t *idx) { + int r; + assert(bus); - assert(message); + assert(m); if (bus->is_kernel) - return bus_kernel_write_message(bus, message); + r = bus_kernel_write_message(bus, m); else - return bus_socket_write_message(bus, message, idx); + r = bus_socket_write_message(bus, m, idx); + + if (r <= 0) + return r; + + if (bus->is_kernel || *idx >= BUS_MESSAGE_SIZE(m)) + log_debug("Sent message type=%s sender=%s destination=%s object=%s interface=%s member=%s cookie=%lu reply_cookie=%lu error=%s", + bus_message_type_to_string(m->header->type), + strna(sd_bus_message_get_sender(m)), + strna(sd_bus_message_get_destination(m)), + strna(sd_bus_message_get_path(m)), + strna(sd_bus_message_get_interface(m)), + strna(sd_bus_message_get_member(m)), + (unsigned long) BUS_MESSAGE_COOKIE(m), + (unsigned long) m->reply_cookie, + strna(m->error.message)); + + return r; } static int dispatch_wqueue(sd_bus *bus) { @@ -1452,7 +1473,8 @@ static int dispatch_rqueue(sd_bus *bus, sd_bus_message **m) { } } -_public_ int sd_bus_send(sd_bus *bus, sd_bus_message *m, uint64_t *serial) { +_public_ int sd_bus_send(sd_bus *bus, sd_bus_message *_m, uint64_t *cookie) { + _cleanup_bus_message_unref_ sd_bus_message *m = sd_bus_message_ref(_m); int r; assert_return(bus, -EINVAL); @@ -1468,18 +1490,24 @@ _public_ int sd_bus_send(sd_bus *bus, sd_bus_message *m, uint64_t *serial) { return -ENOTSUP; } - /* If the serial number isn't kept, then we know that no reply + /* If the cookie number isn't kept, then we know that no reply * is expected */ - if (!serial && !m->sealed) + if (!cookie && !m->sealed) m->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED; r = bus_seal_message(bus, m, 0); if (r < 0) return r; + /* Remarshall if we have to. This will possible unref the + * message and place a replacement in m */ + r = bus_remarshal_message(bus, &m); + if (r < 0) + return r; + /* If this is a reply and no reply was requested, then let's * suppress this, if we can */ - if (m->dont_send && !serial) + if (m->dont_send && !cookie) return 1; if ((bus->state == BUS_RUNNING || bus->state == BUS_HELLO) && bus->wqueue_size <= 0) { @@ -1513,13 +1541,13 @@ _public_ int sd_bus_send(sd_bus *bus, sd_bus_message *m, uint64_t *serial) { bus->wqueue[bus->wqueue_size ++] = sd_bus_message_ref(m); } - if (serial) - *serial = BUS_MESSAGE_SERIAL(m); + if (cookie) + *cookie = BUS_MESSAGE_COOKIE(m); return 1; } -_public_ int sd_bus_send_to(sd_bus *bus, sd_bus_message *m, const char *destination, uint64_t *serial) { +_public_ int sd_bus_send_to(sd_bus *bus, sd_bus_message *m, const char *destination, uint64_t *cookie) { int r; assert_return(bus, -EINVAL); @@ -1537,7 +1565,7 @@ _public_ int sd_bus_send_to(sd_bus *bus, sd_bus_message *m, const char *destinat return r; } - return sd_bus_send(bus, m, serial); + return sd_bus_send(bus, m, cookie); } static usec_t calc_elapse(uint64_t usec) { @@ -1567,12 +1595,13 @@ static int timeout_compare(const void *a, const void *b) { _public_ int sd_bus_call_async( sd_bus *bus, - sd_bus_message *m, + sd_bus_message *_m, sd_bus_message_handler_t callback, void *userdata, uint64_t usec, - uint64_t *serial) { + uint64_t *cookie) { + _cleanup_bus_message_unref_ sd_bus_message *m = sd_bus_message_ref(_m); struct reply_callback *c; int r; @@ -1596,16 +1625,20 @@ _public_ int sd_bus_call_async( if (r < 0) return r; + r = bus_remarshal_message(bus, &m); + if (r < 0) + return r; + c = new0(struct reply_callback, 1); if (!c) return -ENOMEM; c->callback = callback; c->userdata = userdata; - c->serial = BUS_MESSAGE_SERIAL(m); + c->cookie = BUS_MESSAGE_COOKIE(m); c->timeout = calc_elapse(m->timeout); - r = hashmap_put(bus->reply_callbacks, &c->serial, c); + r = hashmap_put(bus->reply_callbacks, &c->cookie, c); if (r < 0) { free(c); return r; @@ -1615,28 +1648,28 @@ _public_ int sd_bus_call_async( r = prioq_put(bus->reply_callbacks_prioq, c, &c->prioq_idx); if (r < 0) { c->timeout = 0; - sd_bus_call_async_cancel(bus, c->serial); + sd_bus_call_async_cancel(bus, c->cookie); return r; } } - r = sd_bus_send(bus, m, serial); + r = sd_bus_send(bus, m, cookie); if (r < 0) { - sd_bus_call_async_cancel(bus, c->serial); + sd_bus_call_async_cancel(bus, c->cookie); return r; } return r; } -_public_ int sd_bus_call_async_cancel(sd_bus *bus, uint64_t serial) { +_public_ int sd_bus_call_async_cancel(sd_bus *bus, uint64_t cookie) { struct reply_callback *c; assert_return(bus, -EINVAL); - assert_return(serial != 0, -EINVAL); + assert_return(cookie != 0, -EINVAL); assert_return(!bus_pid_changed(bus), -ECHILD); - c = hashmap_remove(bus->reply_callbacks, &serial); + c = hashmap_remove(bus->reply_callbacks, &cookie); if (!c) return 0; @@ -1674,13 +1707,14 @@ int bus_ensure_running(sd_bus *bus) { _public_ int sd_bus_call( sd_bus *bus, - sd_bus_message *m, + sd_bus_message *_m, uint64_t usec, sd_bus_error *error, sd_bus_message **reply) { + _cleanup_bus_message_unref_ sd_bus_message *m = sd_bus_message_ref(_m); usec_t timeout; - uint64_t serial; + uint64_t cookie; unsigned i; int r; @@ -1702,7 +1736,11 @@ _public_ int sd_bus_call( if (r < 0) return r; - r = sd_bus_send(bus, m, &serial); + r = bus_remarshal_message(bus, &m); + if (r < 0) + return r; + + r = sd_bus_send(bus, m, &cookie); if (r < 0) return r; @@ -1716,7 +1754,7 @@ _public_ int sd_bus_call( incoming = bus->rqueue[i]; - if (incoming->reply_serial == serial) { + if (incoming->reply_cookie == cookie) { /* Found a match! */ memmove(bus->rqueue + i, bus->rqueue + i + 1, sizeof(sd_bus_message*) * (bus->rqueue_size - i - 1)); @@ -1738,7 +1776,7 @@ _public_ int sd_bus_call( sd_bus_message_unref(incoming); return r; - } else if (incoming->header->serial == serial && + } else if (BUS_MESSAGE_COOKIE(incoming) == cookie && bus->unique_name && incoming->sender && streq(bus->unique_name, incoming->sender)) { @@ -1888,7 +1926,7 @@ static int process_timeout(sd_bus *bus) { r = bus_message_new_synthetic_error( bus, - c->serial, + c->cookie, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_NO_REPLY, "Method call timed out"), &m); if (r < 0) @@ -1901,7 +1939,7 @@ static int process_timeout(sd_bus *bus) { return r; assert_se(prioq_pop(bus->reply_callbacks_prioq) == c); - hashmap_remove(bus->reply_callbacks, &c->serial); + hashmap_remove(bus->reply_callbacks, &c->cookie); bus->current = m; bus->iteration_counter ++; @@ -1931,7 +1969,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_serial != bus->hello_serial) + if (m->reply_cookie != bus->hello_cookie) return -EIO; return 0; @@ -1949,7 +1987,7 @@ static int process_reply(sd_bus *bus, sd_bus_message *m) { m->header->type != SD_BUS_MESSAGE_METHOD_ERROR) return 0; - c = hashmap_remove(bus->reply_callbacks, &m->reply_serial); + c = hashmap_remove(bus->reply_callbacks, &m->reply_cookie); if (!c) return 0; @@ -2030,6 +2068,9 @@ static int process_builtin(sd_bus *bus, sd_bus_message *m) { assert(bus); assert(m); + if (bus->manual_peer_interface) + return 0; + if (m->header->type != SD_BUS_MESSAGE_METHOD_CALL) return 0; @@ -2080,11 +2121,16 @@ static int process_message(sd_bus *bus, sd_bus_message *m) { bus->current = m; bus->iteration_counter++; - log_debug("Got message sender=%s object=%s interface=%s member=%s", + log_debug("Got message type=%s sender=%s destination=%s object=%s interface=%s member=%s cookie=%lu reply_cookie=%lu error=%s", + bus_message_type_to_string(m->header->type), strna(sd_bus_message_get_sender(m)), + strna(sd_bus_message_get_destination(m)), strna(sd_bus_message_get_path(m)), strna(sd_bus_message_get_interface(m)), - strna(sd_bus_message_get_member(m))); + strna(sd_bus_message_get_member(m)), + (unsigned long) BUS_MESSAGE_COOKIE(m), + (unsigned long) m->reply_cookie, + strna(m->error.message)); r = process_hello(bus, m); if (r != 0) @@ -2150,6 +2196,12 @@ static int process_running(sd_bus *bus, sd_bus_message **ret) { if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL) { + log_debug("Unprocessed message call sender=%s object=%s interface=%s member=%s", + strna(sd_bus_message_get_sender(m)), + strna(sd_bus_message_get_path(m)), + strna(sd_bus_message_get_interface(m)), + strna(sd_bus_message_get_member(m))); + r = sd_bus_reply_method_errorf( m, SD_BUS_ERROR_UNKNOWN_OBJECT, @@ -2182,7 +2234,7 @@ static int process_closing(sd_bus *bus, sd_bus_message **ret) { /* First, fail all outstanding method calls */ r = bus_message_new_synthetic_error( bus, - c->serial, + c->cookie, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_NO_REPLY, "Connection terminated"), &m); if (r < 0) @@ -2195,7 +2247,7 @@ static int process_closing(sd_bus *bus, sd_bus_message **ret) { if (c->timeout != 0) prioq_remove(bus->reply_callbacks_prioq, c, &c->prioq_idx); - hashmap_remove(bus->reply_callbacks, &c->serial); + hashmap_remove(bus->reply_callbacks, &c->cookie); bus->current = m; bus->iteration_counter++; @@ -2792,13 +2844,13 @@ static int bus_default(int (*bus_open)(sd_bus **), sd_bus **default_bus, sd_bus } _public_ int sd_bus_default_system(sd_bus **ret) { - static __thread sd_bus *default_system_bus = NULL; + static thread_local sd_bus *default_system_bus = NULL; return bus_default(sd_bus_open_system, &default_system_bus, ret); } _public_ int sd_bus_default_user(sd_bus **ret) { - static __thread sd_bus *default_user_bus = NULL; + static thread_local sd_bus *default_user_bus = NULL; return bus_default(sd_bus_open_user, &default_user_bus, ret); } @@ -2935,3 +2987,25 @@ _public_ int sd_bus_get_peer_creds(sd_bus *bus, uint64_t mask, sd_bus_creds **re *ret = c; return 0; } + +_public_ int sd_bus_try_close(sd_bus *bus) { + int r; + + assert_return(bus, -EINVAL); + assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN); + assert_return(!bus_pid_changed(bus), -ECHILD); + assert_return(bus->is_kernel, -ENOTSUP); + + if (bus->rqueue_size > 0) + return -EBUSY; + + if (bus->wqueue_size > 0) + return -EBUSY; + + r = bus_kernel_try_close(bus); + if (r < 0) + return r; + + sd_bus_close(bus); + return 0; +}