We need this since we might need to invoke the release ioctl for
messages. Since we don't want to add any locking for that we simply keep
a reference to the bus and then rely that the fd stays valid all the
time.
BUS_OPENING,
BUS_AUTHENTICATING,
BUS_HELLO,
BUS_OPENING,
BUS_AUTHENTICATING,
BUS_HELLO,
+ BUS_RUNNING,
+ BUS_CLOSED
+static inline bool BUS_IS_OPEN(enum bus_state state) {
+ return state > BUS_UNSET && state < BUS_CLOSED;
+}
+
enum bus_auth {
_BUS_AUTH_INVALID,
BUS_AUTH_EXTERNAL,
enum bus_auth {
_BUS_AUTH_INVALID,
BUS_AUTH_EXTERNAL,
if (m->release_kdbus)
ioctl(m->bus->input_fd, KDBUS_CMD_MSG_RELEASE, m->kdbus);
if (m->release_kdbus)
ioctl(m->bus->input_fd, KDBUS_CMD_MSG_RELEASE, m->kdbus);
+ if (m->bus)
+ sd_bus_unref(m->bus);
+
if (m->free_fds) {
close_many(m->fds, m->n_fds);
free(m->fds);
}
if (m->free_fds) {
close_many(m->fds, m->n_fds);
free(m->fds);
}
- if (m->bus)
- sd_bus_unref(m->bus);
-
if (m->iovec != m->iovec_fixed)
free(m->iovec);
if (m->iovec != m->iovec_fixed)
free(m->iovec);
static int bus_poll(sd_bus *bus, bool need_more, uint64_t timeout_usec);
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;
static void bus_free(sd_bus *b) {
struct filter_callback *f;
struct object_callback *c;
free(b->rbuffer);
free(b->unique_name);
free(b->rbuffer);
free(b->unique_name);
- 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->state = BUS_CLOSED;
- bus->input_fd = bus->output_fd = -1;
+ 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) {
}
sd_bus *sd_bus_ref(sd_bus *bus) {
if (!bus)
return -EINVAL;
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) {
}
int sd_bus_can_send(sd_bus *bus, char type) {
if (!bus)
return -EINVAL;
if (!bus)
return -EINVAL;
- if (bus->output_fd < 0)
+ if (bus->state == BUS_UNSET)
return -ENOTCONN;
if (type == SD_BUS_TYPE_UNIX_FD) {
return -ENOTCONN;
if (type == SD_BUS_TYPE_UNIX_FD) {
assert(bus);
assert(bus->state == BUS_RUNNING || bus->state == BUS_HELLO);
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)
while (bus->wqueue_size > 0) {
if (bus->is_kernel)
assert(m);
assert(bus->state == BUS_RUNNING || bus->state == BUS_HELLO);
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->rqueue_size > 0) {
/* Dispatch a queued message */
if (!bus)
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;
return -ENOTCONN;
if (!m)
return -EINVAL;
if (!bus)
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;
return -ENOTCONN;
if (!m)
return -EINVAL;
- if (bus->input_fd < 0)
- return -ENOTCONN;
- if (bus->state == BUS_UNSET)
+ if (bus->state == BUS_UNSET || bus->state == BUS_CLOSED)
if (bus->state == BUS_RUNNING)
return 1;
if (bus->state == BUS_RUNNING)
return 1;
if (!bus)
return -EINVAL;
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;
return -ENOTCONN;
if (!m)
return -EINVAL;
int sd_bus_get_fd(sd_bus *bus) {
if (!bus)
return -EINVAL;
int sd_bus_get_fd(sd_bus *bus) {
if (!bus)
return -EINVAL;
+ if (!BUS_IS_OPEN(bus->state))
return -ENOTCONN;
if (bus->input_fd != bus->output_fd)
return -EPERM;
return -ENOTCONN;
if (bus->input_fd != bus->output_fd)
return -EPERM;
if (!bus)
return -EINVAL;
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 -ENOTCONN;
if (bus->state == BUS_OPENING)
return -EINVAL;
if (!timeout_usec)
return -EINVAL;
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) {
return -ENOTCONN;
if (bus->state == BUS_AUTHENTICATING) {
if (!bus)
return -EINVAL;
if (!bus)
return -EINVAL;
- if (bus->input_fd < 0)
- return -ENOTCONN;
/* We don't allow recursively invoking sd_bus_process(). */
if (bus->processing)
/* We don't allow recursively invoking sd_bus_process(). */
if (bus->processing)
switch (bus->state) {
case BUS_UNSET:
switch (bus->state) {
case BUS_UNSET:
return -ENOTCONN;
case BUS_OPENING:
return -ENOTCONN;
case BUS_OPENING:
+ if (!BUS_IS_OPEN(bus->state))
return -ENOTCONN;
e = sd_bus_get_events(bus);
return -ENOTCONN;
e = sd_bus_get_events(bus);
if (!bus)
return -EINVAL;
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;
return -ENOTCONN;
if (bus->rqueue_size > 0)
return 0;
if (!bus)
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;
r = bus_ensure_running(bus);
return -ENOTCONN;
r = bus_ensure_running(bus);