diff options
author | Lennart Poettering <lennart@poettering.net> | 2013-11-30 01:02:51 +0100 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2013-11-30 01:02:51 +0100 |
commit | a43b9ca3049d0f27cdb3bc8dad703e688cba31b3 (patch) | |
tree | 3a459cde6758bdb6f2cad5b280251930eee4f7d4 /src/libsystemd-bus/bus-kernel.c | |
parent | 7adc46fcce257fcf4c83faa18b8c78f2a577e4f1 (diff) |
bus: synthesize local error reply when we cannot deliver a message to kdbus because the destination is unavailable
Diffstat (limited to 'src/libsystemd-bus/bus-kernel.c')
-rw-r--r-- | src/libsystemd-bus/bus-kernel.c | 51 |
1 files changed, 49 insertions, 2 deletions
diff --git a/src/libsystemd-bus/bus-kernel.c b/src/libsystemd-bus/bus-kernel.c index a8579c98fa..69143434b3 100644 --- a/src/libsystemd-bus/bus-kernel.c +++ b/src/libsystemd-bus/bus-kernel.c @@ -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; } |