bus: synthesize timeout message errors instead of returning error codes

This commit is contained in:
Lennart Poettering 2013-05-16 21:14:56 +02:00
parent 5cbe749238
commit eb01ba5de1
10 changed files with 177 additions and 42 deletions

16
TODO
View File

@ -29,6 +29,22 @@ Fedora 19:
Features:
* libsystemd-bus:
- default policy (allow uid == 0 and our own uid)
- enforce alignment of pointers passed in
- negotiation for attach attributes
- verify that the PID doesn't change for existing busses
- when kdbus doesn't take our message without memfds, try again with memfds
- kdbus: generate correct bloom filter for matches
- implement translator service
- port systemd to new library
- implement busname unit type in systemd
- move to gvariant
- minimal locking around the memfd cache
- keep the connection fds around as long as the bus is open
- make ref counting atomic
- merge busctl into systemctl or so?
* in the final killing spree, detect processes from the root directory, and
complain loudly if they have argv[0][0] == '@' set.
https://bugzilla.redhat.com/show_bug.cgi?id=961044

View File

@ -142,6 +142,9 @@ int bus_error_to_errno(const sd_bus_error* e) {
/* Better replce this with a gperf table */
if (!e)
return -EIO;
if (!e->name)
return -EIO;
@ -152,6 +155,30 @@ int bus_error_to_errno(const sd_bus_error* e) {
streq(e->name, "org.freedesktop.DBus.Error.AccessDenied"))
return -EPERM;
if (streq(e->name, "org.freedesktop.DBus.Error.InvalidArgs"))
return -EINVAL;
if (streq(e->name, "org.freedesktop.DBus.Error.UnixProcessIdUnknown"))
return -ESRCH;
if (streq(e->name, "org.freedesktop.DBus.Error.FileNotFound"))
return -ENOENT;
if (streq(e->name, "org.freedesktop.DBus.Error.FileExists"))
return -EEXIST;
if (streq(e->name, "org.freedesktop.DBus.Error.Timeout"))
return -ETIMEDOUT;
if (streq(e->name, "org.freedesktop.DBus.Error.IOError"))
return -EIO;
if (streq(e->name, "org.freedesktop.DBus.Error.Disconnected"))
return -ECONNRESET;
if (streq(e->name, "org.freedesktop.DBus.Error.NotSupported"))
return -ENOTSUP;
return -EIO;
}
@ -159,13 +186,54 @@ int bus_error_from_errno(sd_bus_error *e, int error) {
if (!e)
return error;
if (error == -ENOMEM)
sd_bus_error_set_const(e, "org.freedesktop.DBus.Error.NoMemory", strerror(-error));
else if (error == -EPERM || error == -EACCES)
sd_bus_error_set_const(e, "org.freedesktop.DBus.Error.AccessDenied", strerror(-error));
else
sd_bus_error_set_const(e, "org.freedesktop.DBus.Error.Failed", "Operation failed");
switch (error) {
case -ENOMEM:
sd_bus_error_set_const(e, "org.freedesktop.DBus.Error.NoMemory", "Out of memory");
break;
case -EPERM:
case -EACCES:
sd_bus_error_set_const(e, "org.freedesktop.DBus.Error.AccessDenied", "Access denied");
break;
case -EINVAL:
sd_bus_error_set_const(e, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid argument");
break;
case -ESRCH:
sd_bus_error_set_const(e, "org.freedesktop.DBus.Error.UnixProcessIdUnknown", "No such process");
break;
case -ENOENT:
sd_bus_error_set_const(e, "org.freedesktop.DBus.Error.FileNotFound", "File not found");
break;
case -EEXIST:
sd_bus_error_set_const(e, "org.freedesktop.DBus.Error.FileExists", "File exists");
break;
case -ETIMEDOUT:
case -ETIME:
sd_bus_error_set_const(e, "org.freedesktop.DBus.Error.Timeout", "Timed out");
break;
case -EIO:
sd_bus_error_set_const(e, "org.freedesktop.DBus.Error.IOError", "Input/output error");
break;
case -ENETRESET:
case -ECONNABORTED:
case -ECONNRESET:
sd_bus_error_set_const(e, "org.freedesktop.DBus.Error.Disconnected", "Disconnected");
break;
case -ENOTSUP:
sd_bus_error_set_const(e, "org.freedesktop.DBus.Error.NotSupported", "Not supported");
break;
}
sd_bus_error_set_const(e, "org.freedesktop.DBus.Error.Failed", "Operation failed");
return error;
}

View File

@ -199,7 +199,6 @@ static bool value_node_same(
int bus_match_run(
sd_bus *bus,
struct bus_match_node *node,
int ret,
sd_bus_message *m) {
@ -230,7 +229,7 @@ int bus_match_run(
* we won't call any. The children of the root node
* are compares or leaves, they will automatically
* call their siblings. */
return bus_match_run(bus, node->child, ret, m);
return bus_match_run(bus, node->child, m);
case BUS_MATCH_VALUE:
@ -240,7 +239,7 @@ int bus_match_run(
* automatically call their siblings */
assert(node->child);
return bus_match_run(bus, node->child, ret, m);
return bus_match_run(bus, node->child, m);
case BUS_MATCH_LEAF:
@ -257,11 +256,11 @@ int bus_match_run(
/* Run the callback. And then invoke siblings. */
assert(node->leaf.callback);
r = node->leaf.callback(bus, ret, m, node->leaf.userdata);
r = node->leaf.callback(bus, m, node->leaf.userdata);
if (r != 0)
return r;
return bus_match_run(bus, node->next, ret, m);
return bus_match_run(bus, node->next, m);
case BUS_MATCH_MESSAGE_TYPE:
test_u8 = m->header->type;
@ -318,7 +317,7 @@ int bus_match_run(
found = NULL;
if (found) {
r = bus_match_run(bus, found, ret, m);
r = bus_match_run(bus, found, m);
if (r != 0)
return r;
}
@ -331,7 +330,7 @@ int bus_match_run(
if (!value_node_test(c, node->type, test_u8, test_str))
continue;
r = bus_match_run(bus, c, ret, m);
r = bus_match_run(bus, c, m);
if (r != 0)
return r;
}
@ -341,7 +340,7 @@ int bus_match_run(
return 0;
/* And now, let's invoke our siblings */
return bus_match_run(bus, node->next, ret, m);
return bus_match_run(bus, node->next, m);
}
static int bus_match_add_compare_value(

View File

@ -69,7 +69,7 @@ struct bus_match_node {
};
};
int bus_match_run(sd_bus *bus, struct bus_match_node *root, int ret, sd_bus_message *m);
int bus_match_run(sd_bus *bus, struct bus_match_node *root, sd_bus_message *m);
int bus_match_add(struct bus_match_node *root, const char *match, sd_bus_message_handler_t callback, void *userdata, struct bus_match_node **ret);
int bus_match_remove(struct bus_match_node *root, const char *match, sd_bus_message_handler_t callback, void *userdata);

View File

@ -623,6 +623,43 @@ fail:
return r;
}
int bus_message_new_synthetic_error(
sd_bus *bus,
uint64_t serial,
const sd_bus_error *e,
sd_bus_message **m) {
sd_bus_message *t;
int r;
assert(sd_bus_error_is_set(e));
assert(m);
t = message_new(bus, SD_BUS_MESSAGE_TYPE_METHOD_ERROR);
if (!t)
return -ENOMEM;
t->header->flags |= SD_BUS_MESSAGE_NO_REPLY_EXPECTED;
t->reply_serial = serial;
r = message_append_field_uint32(t, SD_BUS_MESSAGE_HEADER_REPLY_SERIAL, t->reply_serial);
if (r < 0)
goto fail;
if (bus && bus->unique_name) {
r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, bus->unique_name, &t->destination);
if (r < 0)
goto fail;
}
*m = t;
return 0;
fail:
message_free(t);
return r;
}
sd_bus_message* sd_bus_message_ref(sd_bus_message *m) {
if (!m)
return NULL;
@ -4240,3 +4277,12 @@ int bus_header_message_size(struct bus_header *h, size_t *sum) {
*sum = sizeof(struct bus_header) + ALIGN8(fs) + bs;
return 0;
}
int bus_message_to_errno(sd_bus_message *m) {
assert(m);
if (m->header->type != SD_BUS_MESSAGE_TYPE_METHOD_ERROR)
return 0;
return bus_error_to_errno(&m->error);
}

View File

@ -235,3 +235,7 @@ struct bus_body_part *message_append_part(sd_bus_message *m);
int bus_body_part_map(struct bus_body_part *part);
void bus_body_part_unmap(struct bus_body_part *part);
int bus_message_to_errno(sd_bus_message *m);
int bus_message_new_synthetic_error(sd_bus *bus, uint64_t serial, const sd_bus_error *e, sd_bus_message **m);

View File

@ -229,18 +229,18 @@ int sd_bus_set_anonymous(sd_bus *bus, int b) {
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;
@ -1523,6 +1523,7 @@ int sd_bus_get_timeout(sd_bus *bus, uint64_t *timeout_usec) {
}
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;
@ -1537,10 +1538,18 @@ static int process_timeout(sd_bus *bus) {
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;
@ -1590,7 +1599,7 @@ static int process_reply(sd_bus *bus, sd_bus_message *m) {
if (r < 0)
return r;
r = c->callback(bus, 0, m, c->userdata);
r = c->callback(bus, m, c->userdata);
free(c);
return r;
@ -1621,7 +1630,7 @@ static int process_filter(sd_bus *bus, sd_bus_message *m) {
if (r < 0)
return r;
r = l->callback(bus, 0, m, l->userdata);
r = l->callback(bus, m, l->userdata);
if (r != 0)
return r;
@ -1641,7 +1650,7 @@ static int process_match(sd_bus *bus, sd_bus_message *m) {
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;
@ -1734,7 +1743,7 @@ static int process_object(sd_bus *bus, sd_bus_message *m) {
if (r < 0)
return r;
r = c->callback(bus, 0, m, c->userdata);
r = c->callback(bus, m, c->userdata);
if (r != 0)
return r;
@ -1764,7 +1773,7 @@ static int process_object(sd_bus *bus, sd_bus_message *m) {
if (r < 0)
return r;
r = c->callback(bus, 0, m, c->userdata);
r = c->callback(bus, m, c->userdata);
if (r != 0)
return r;

View File

@ -35,17 +35,17 @@
#include "bus-match.h"
#include "bus-internal.h"
static int match_callback(sd_bus *bus, int error, sd_bus_message *m, void *userdata) {
static int match_callback(sd_bus *bus, sd_bus_message *m, void *userdata) {
log_info("Match triggered! interface=%s member=%s", strna(sd_bus_message_get_interface(m)), strna(sd_bus_message_get_member(m)));
return 0;
}
static int object_callback(sd_bus *bus, int error, sd_bus_message *m, void *userdata) {
static int object_callback(sd_bus *bus, sd_bus_message *m, void *userdata) {
int r;
assert(bus);
if (error != 0)
if (sd_bus_message_is_method_error(m, NULL))
return 0;
if (sd_bus_message_is_method_call(m, "org.object.test", "Foobar")) {
@ -356,10 +356,10 @@ finish:
return INT_TO_PTR(r);
}
static int quit_callback(sd_bus *b, int ret, sd_bus_message *m, void *userdata) {
static int quit_callback(sd_bus *b, sd_bus_message *m, void *userdata) {
bool *x = userdata;
log_error("Quit callback: %s", strerror(ret));
log_error("Quit callback: %s", strerror(bus_message_to_errno(m)));
*x = 1;
return 1;

View File

@ -30,7 +30,7 @@
static bool mask[32];
static int filter(sd_bus *b, int ret, sd_bus_message *m, void *userdata) {
static int filter(sd_bus *b, sd_bus_message *m, void *userdata) {
log_info("Ran %i", PTR_TO_INT(userdata));
mask[PTR_TO_INT(userdata)] = true;
return 0;
@ -85,7 +85,7 @@ int main(int argc, char *argv[]) {
assert_se(bus_message_seal(m, 1) >= 0);
zero(mask);
assert_se(bus_match_run(NULL, &root, 0, m) == 0);
assert_se(bus_match_run(NULL, &root, m) == 0);
assert_se(mask_contains((unsigned[]) { 9, 8, 7, 5, 10, 12, 13, 14 }, 8));
assert_se(bus_match_remove(&root, "member='waldo',path='/foo/bar'", filter, INT_TO_PTR(8)) > 0);
@ -95,7 +95,7 @@ int main(int argc, char *argv[]) {
bus_match_dump(&root, 0);
zero(mask);
assert_se(bus_match_run(NULL, &root, 0, m) == 0);
assert_se(bus_match_run(NULL, &root, m) == 0);
assert_se(mask_contains((unsigned[]) { 9, 5, 10, 12, 14, 7 }, 6));
for (i = 0; i < _BUS_MATCH_NODE_TYPE_MAX; i++) {

View File

@ -41,13 +41,6 @@ extern "C" {
# endif
#endif
/* TODO:
* - merge busctl into systemctl or so?
* - default policy (allow uid == 0 and our own uid)
* - enforce alignment of pointers passed in
* - negotiation for attach attributes
*/
typedef struct sd_bus sd_bus;
typedef struct sd_bus_message sd_bus_message;
@ -57,7 +50,7 @@ typedef struct {
int need_free;
} sd_bus_error;
typedef int (*sd_bus_message_handler_t)(sd_bus *bus, int ret, sd_bus_message *m, void *userdata);
typedef int (*sd_bus_message_handler_t)(sd_bus *bus, sd_bus_message *m, void *userdata);
/* Connections */