#include "macro.h"
#include "strv.h"
#include "set.h"
+#include "missing.h"
#include "sd-bus.h"
#include "bus-internal.h"
static int bus_poll(sd_bus *bus, bool need_more, uint64_t timeout_usec);
+static void bus_close_fds(sd_bus *b) {
+ assert(b);
+
+ if (b->input_fd >= 0)
+ close_nointr_nofail(b->input_fd);
+
+ if (b->output_fd >= 0 && b->output_fd != b->input_fd)
+ close_nointr_nofail(b->output_fd);
+
+ b->input_fd = b->output_fd = -1;
+}
+
static void bus_free(sd_bus *b) {
struct filter_callback *f;
struct object_callback *c;
assert(b);
- sd_bus_close(b);
+ bus_close_fds(b);
free(b->rbuffer);
free(b->unique_name);
free(b->auth_buffer);
free(b->address);
+ free(b->kernel);
free(b->exec_path);
strv_free(b->exec_argv);
}
hashmap_free(b->object_callbacks);
-
bus_match_free(&b->match_callbacks);
+ bus_kernel_flush_memfd(b);
+
free(b);
}
if (!r)
return -ENOMEM;
- r->n_ref = 1;
+ r->n_ref = REFCNT_INIT;
r->input_fd = r->output_fd = -1;
r->message_version = 1;
r->negotiate_fds = true;
return 0;
}
-static int hello_callback(sd_bus *bus, int error, sd_bus_message *reply, void *userdata) {
+static int hello_callback(sd_bus *bus, sd_bus_message *reply, void *userdata) {
const char *s;
int r;
assert(bus);
assert(bus->state == BUS_HELLO);
-
- if (error != 0)
- return -error;
-
assert(reply);
+ r = bus_message_to_errno(reply);
+ if (r < 0)
+ return r;
+
r = sd_bus_message_read(reply, "s", &s);
if (r < 0)
return r;
int bus_start_running(sd_bus *bus) {
assert(bus);
- if (bus->bus_client) {
+ if (bus->bus_client && !bus->is_kernel) {
bus->state = BUS_HELLO;
return 1;
}
if (r < 0)
return r;
- e = getenv("DBUS_SYSTEM_BUS_ADDRESS");
+ e = secure_getenv("DBUS_SYSTEM_BUS_ADDRESS");
if (e) {
r = sd_bus_set_address(b, e);
if (r < 0)
if (r < 0)
return r;
- e = getenv("DBUS_SESSION_BUS_ADDRESS");
+ e = secure_getenv("DBUS_SESSION_BUS_ADDRESS");
if (e) {
r = sd_bus_set_address(b, e);
if (r < 0)
goto fail;
} else {
- e = getenv("XDG_RUNTIME_DIR");
+ e = secure_getenv("XDG_RUNTIME_DIR");
if (!e) {
r = -ENOENT;
goto fail;
if (!bus)
return;
- if (bus->input_fd >= 0)
- close_nointr_nofail(bus->input_fd);
- if (bus->output_fd >= 0 && bus->output_fd != bus->input_fd)
- close_nointr_nofail(bus->output_fd);
+ if (bus->state != BUS_CLOSED)
+ return;
- bus->input_fd = bus->output_fd = -1;
+ bus->state = BUS_CLOSED;
+
+ if (!bus->is_kernel)
+ bus_close_fds(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_MSG_RELEASE ioctl on the fd when they are
+ * freed. */
}
sd_bus *sd_bus_ref(sd_bus *bus) {
if (!bus)
return NULL;
- assert(bus->n_ref > 0);
+ assert_se(REFCNT_INC(bus->n_ref) >= 2);
- bus->n_ref++;
return bus;
}
if (!bus)
return NULL;
- assert(bus->n_ref > 0);
- bus->n_ref--;
-
- if (bus->n_ref <= 0)
+ if (REFCNT_DEC(bus->n_ref) <= 0)
bus_free(bus);
return NULL;
if (!bus)
return -EINVAL;
- return bus->state != BUS_UNSET && bus->input_fd >= 0;
+ return BUS_IS_OPEN(bus->state);
}
int sd_bus_can_send(sd_bus *bus, char type) {
if (!bus)
return -EINVAL;
- if (bus->output_fd < 0)
+ if (bus->state == BUS_UNSET)
return -ENOTCONN;
if (type == SD_BUS_TYPE_UNIX_FD) {
assert(bus);
assert(bus->state == BUS_RUNNING || bus->state == BUS_HELLO);
- if (bus->output_fd < 0)
- return -ENOTCONN;
-
while (bus->wqueue_size > 0) {
if (bus->is_kernel)
assert(m);
assert(bus->state == BUS_RUNNING || bus->state == BUS_HELLO);
- if (bus->input_fd < 0)
- return -ENOTCONN;
-
if (bus->rqueue_size > 0) {
/* Dispatch a queued message */
if (!bus)
return -EINVAL;
- if (bus->state == BUS_UNSET)
- return -ENOTCONN;
- if (bus->output_fd < 0)
+ if (!BUS_IS_OPEN(bus->state))
return -ENOTCONN;
if (!m)
return -EINVAL;
if (!bus)
return -EINVAL;
- if (bus->state == BUS_UNSET)
- return -ENOTCONN;
- if (bus->output_fd < 0)
+ if (!BUS_IS_OPEN(bus->state))
return -ENOTCONN;
if (!m)
return -EINVAL;
assert(bus);
- if (bus->input_fd < 0)
- return -ENOTCONN;
- if (bus->state == BUS_UNSET)
+ if (bus->state == BUS_UNSET || bus->state == BUS_CLOSED)
return -ENOTCONN;
-
if (bus->state == BUS_RUNNING)
return 1;
if (!bus)
return -EINVAL;
- if (bus->output_fd < 0)
- return -ENOTCONN;
- if (bus->state == BUS_UNSET)
+ if (!BUS_IS_OPEN(bus->state))
return -ENOTCONN;
if (!m)
return -EINVAL;
int sd_bus_get_fd(sd_bus *bus) {
if (!bus)
return -EINVAL;
- if (bus->input_fd < 0)
+ if (!BUS_IS_OPEN(bus->state))
return -ENOTCONN;
if (bus->input_fd != bus->output_fd)
return -EPERM;
if (!bus)
return -EINVAL;
- if (bus->state == BUS_UNSET)
- return -ENOTCONN;
- if (bus->input_fd < 0)
+ if (!BUS_IS_OPEN(bus->state))
return -ENOTCONN;
if (bus->state == BUS_OPENING)
return -EINVAL;
if (!timeout_usec)
return -EINVAL;
- if (bus->state == BUS_UNSET)
- return -ENOTCONN;
- if (bus->input_fd < 0)
+ if (!BUS_IS_OPEN(bus->state))
return -ENOTCONN;
if (bus->state == BUS_AUTHENTICATING) {
}
static int process_timeout(sd_bus *bus) {
+ _cleanup_bus_message_unref_ sd_bus_message* m = NULL;
struct reply_callback *c;
usec_t n;
int r;
if (c->timeout > n)
return 0;
+ r = bus_message_new_synthetic_error(
+ bus,
+ c->serial,
+ &SD_BUS_ERROR_MAKE("org.freedesktop.DBus.Error.Timeout", "Timed out"),
+ &m);
+ if (r < 0)
+ return r;
+
assert_se(prioq_pop(bus->reply_callbacks_prioq) == c);
hashmap_remove(bus->reply_callbacks, &c->serial);
- r = c->callback(bus, ETIMEDOUT, NULL, c->userdata);
+ r = c->callback(bus, m, c->userdata);
free(c);
return r < 0 ? r : 1;
if (c->timeout != 0)
prioq_remove(bus->reply_callbacks_prioq, c, &c->prioq_idx);
- r = c->callback(bus, 0, m, c->userdata);
+ r = sd_bus_message_rewind(m, true);
+ if (r < 0)
+ return r;
+
+ r = c->callback(bus, m, c->userdata);
free(c);
return r;
l->last_iteration = bus->iteration_counter;
- r = l->callback(bus, 0, m, l->userdata);
+ r = sd_bus_message_rewind(m, true);
+ if (r < 0)
+ return r;
+
+ r = l->callback(bus, m, l->userdata);
if (r != 0)
return r;
do {
bus->match_callbacks_modified = false;
- r = bus_match_run(bus, &bus->match_callbacks, 0, m);
+ r = bus_match_run(bus, &bus->match_callbacks, m);
if (r != 0)
return r;
c->last_iteration = bus->iteration_counter;
- r = c->callback(bus, 0, m, c->userdata);
+ r = sd_bus_message_rewind(m, true);
+ if (r < 0)
+ return r;
+
+ r = c->callback(bus, m, c->userdata);
if (r != 0)
return r;
c->last_iteration = bus->iteration_counter;
- r = c->callback(bus, 0, m, c->userdata);
+ r = sd_bus_message_rewind(m, true);
+ if (r < 0)
+ return r;
+
+ r = c->callback(bus, m, c->userdata);
if (r != 0)
return r;
if (p)
*p = 0;
- r = set_put(s, a);
- if (r < 0) {
- free(a);
-
- if (r != -EEXIST)
- return r;
- }
+ r = set_consume(s, a);
+ if (r < 0 && r != -EEXIST)
+ return r;
}
f = open_memstream(&introspection, &size);
goto null_message;
if (ret) {
+ r = sd_bus_message_rewind(m, true);
+ if (r < 0)
+ return r;
+
*ret = m;
m = NULL;
return 1;
if (!bus)
return -EINVAL;
- if (bus->input_fd < 0)
- return -ENOTCONN;
/* We don't allow recursively invoking sd_bus_process(). */
if (bus->processing)
switch (bus->state) {
case BUS_UNSET:
+ case BUS_CLOSED:
return -ENOTCONN;
case BUS_OPENING:
assert(bus);
- if (bus->input_fd < 0)
+ if (!BUS_IS_OPEN(bus->state))
return -ENOTCONN;
e = sd_bus_get_events(bus);
if (!bus)
return -EINVAL;
- if (bus->state == BUS_UNSET)
- return -ENOTCONN;
- if (bus->input_fd < 0)
+ if (!BUS_IS_OPEN(bus->state))
return -ENOTCONN;
if (bus->rqueue_size > 0)
return 0;
if (!bus)
return -EINVAL;
- if (bus->state == BUS_UNSET)
- return -ENOTCONN;
- if (bus->output_fd < 0)
+ if (!BUS_IS_OPEN(bus->state))
return -ENOTCONN;
r = bus_ensure_running(bus);