mirror of
https://github.com/systemd/systemd.git
synced 2026-08-04 23:20:32 +00:00
bus: synthesize local error reply when we cannot deliver a message to kdbus because the destination is unavailable
This commit is contained in:
@@ -393,13 +393,60 @@ int bus_kernel_write_message(sd_bus *bus, sd_bus_message *m) {
|
||||
assert(m);
|
||||
assert(bus->state == BUS_RUNNING);
|
||||
|
||||
/* If we can't deliver, we want room for the error message */
|
||||
r = bus_rqueue_make_room(bus);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = bus_message_setup_kmsg(bus, m);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = ioctl(bus->output_fd, KDBUS_CMD_MSG_SEND, m->kdbus);
|
||||
if (r < 0)
|
||||
return errno == EAGAIN ? 0 : -errno;
|
||||
if (r < 0) {
|
||||
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
|
||||
sd_bus_message *reply;
|
||||
|
||||
if (errno == EAGAIN || errno == EINTR)
|
||||
return 0;
|
||||
else if (errno == ENXIO || errno == ESRCH) {
|
||||
|
||||
/* ENXIO: unique name not known
|
||||
* ESRCH: well-known name not known */
|
||||
|
||||
if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
|
||||
sd_bus_error_setf(&error, SD_BUS_ERROR_SERVICE_UNKNOWN, "Destination %s not known", m->destination);
|
||||
else
|
||||
return 0;
|
||||
|
||||
} else if (errno == EADDRNOTAVAIL) {
|
||||
|
||||
/* EADDRNOTAVAIL: activation is possible, but turned off in request flags */
|
||||
|
||||
if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
|
||||
sd_bus_error_setf(&error, SD_BUS_ERROR_SERVICE_UNKNOWN, "Activation of %s not requested", m->destination);
|
||||
else
|
||||
return 0;
|
||||
} else
|
||||
return -errno;
|
||||
|
||||
r = bus_message_new_synthetic_error(
|
||||
bus,
|
||||
BUS_MESSAGE_SERIAL(m),
|
||||
&error,
|
||||
&reply);
|
||||
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = bus_seal_synthetic_message(bus, reply);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
bus->rqueue[bus->rqueue_size++] = reply;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -1274,9 +1274,9 @@ static int bus_write_message(sd_bus *bus, sd_bus_message *message, size_t *idx)
|
||||
assert(message);
|
||||
|
||||
if (bus->is_kernel)
|
||||
r = bus_kernel_write_message(bus, message);
|
||||
return bus_kernel_write_message(bus, message);
|
||||
else
|
||||
r = bus_socket_write_message(bus, message, idx);
|
||||
return bus_socket_write_message(bus, message, idx);
|
||||
|
||||
return r;
|
||||
}
|
||||
@@ -1627,20 +1627,17 @@ _public_ int sd_bus_call(
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
i = bus->rqueue_size;
|
||||
|
||||
r = sd_bus_send(bus, m, &serial);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
timeout = calc_elapse(usec);
|
||||
i = bus->rqueue_size;
|
||||
|
||||
for (;;) {
|
||||
usec_t left;
|
||||
|
||||
r = bus_read_message(bus);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
while (i < bus->rqueue_size) {
|
||||
sd_bus_message *incoming = NULL;
|
||||
|
||||
@@ -1660,24 +1657,13 @@ _public_ int sd_bus_call(
|
||||
sd_bus_message_unref(incoming);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (incoming->header->type == SD_BUS_MESSAGE_METHOD_ERROR) {
|
||||
int k;
|
||||
|
||||
} else if (incoming->header->type == SD_BUS_MESSAGE_METHOD_ERROR)
|
||||
r = sd_bus_error_copy(error, &incoming->error);
|
||||
if (r < 0) {
|
||||
sd_bus_message_unref(incoming);
|
||||
return r;
|
||||
}
|
||||
|
||||
k = sd_bus_error_get_errno(&incoming->error);
|
||||
sd_bus_message_unref(incoming);
|
||||
return -k;
|
||||
}
|
||||
else
|
||||
r = -EIO;
|
||||
|
||||
sd_bus_message_unref(incoming);
|
||||
return -EIO;
|
||||
return r;
|
||||
|
||||
} else if (incoming->header->serial == serial &&
|
||||
bus->unique_name &&
|
||||
@@ -1700,6 +1686,9 @@ _public_ int sd_bus_call(
|
||||
i++;
|
||||
}
|
||||
|
||||
r = bus_read_message(bus);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r > 0)
|
||||
continue;
|
||||
|
||||
|
||||
@@ -35,6 +35,7 @@ int main(int argc, char *argv[]) {
|
||||
_cleanup_close_ int bus_ref = -1;
|
||||
_cleanup_free_ char *bus_name = NULL, *address = NULL;
|
||||
_cleanup_bus_message_unref_ sd_bus_message *m = NULL;
|
||||
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
|
||||
const char *ua = NULL, *ub = NULL, *the_string = NULL;
|
||||
sd_bus *a, *b;
|
||||
int r, pipe_fds[2];
|
||||
@@ -84,6 +85,10 @@ int main(int argc, char *argv[]) {
|
||||
|
||||
printf("unique b: %s\n", ub);
|
||||
|
||||
r = sd_bus_call_method(a, "this.doesnt.exist", "/foo", "meh.mah", "muh", &error, NULL, "s", "yayayay");
|
||||
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);
|
||||
assert_se(r >= 0);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user