X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Fcore%2Fdbus.c;h=aa3d93bf06f315a342970a56a8958ab5a4f798cc;hp=08aff1fd2b03a64a92e8cac3028b1f58baedca4b;hb=cac914e643a50c72893c5478f6886e0978f8fa18;hpb=92f303495868f7d6971b7f42c69f63cb0e2e0ebd diff --git a/src/core/dbus.c b/src/core/dbus.c index 08aff1fd2..aa3d93bf0 100644 --- a/src/core/dbus.c +++ b/src/core/dbus.c @@ -28,7 +28,6 @@ #include "dbus.h" #include "log.h" #include "strv.h" -#include "cgroup.h" #include "mkdir.h" #include "missing.h" #include "dbus-unit.h" @@ -48,7 +47,7 @@ #include "special.h" #include "dbus-common.h" -#define CONNECTIONS_MAX 52 +#define CONNECTIONS_MAX 512 /* Well-known address (http://dbus.freedesktop.org/doc/dbus-specification.html#message-bus-types) */ #define DBUS_SYSTEM_BUS_DEFAULT_ADDRESS "unix:path=/var/run/dbus/system_bus_socket" @@ -203,13 +202,11 @@ static void bus_toggle_watch(DBusWatch *bus_watch, void *data) { } static int bus_timeout_arm(Manager *m, Watch *w) { - struct itimerspec its; + struct itimerspec its = {}; assert(m); assert(w); - zero(its); - if (dbus_timeout_get_enabled(w->data.bus_timeout)) { timespec_store(&its.it_value, dbus_timeout_get_interval(w->data.bus_timeout) * USEC_PER_MSEC); its.it_interval = its.it_value; @@ -365,8 +362,8 @@ static DBusHandlerResult api_bus_message_filter(DBusConnection *connection, DBus log_debug("Got D-Bus activation request for %s", name); - if (manager_unit_pending_inactive(m, SPECIAL_DBUS_SERVICE) || - manager_unit_pending_inactive(m, SPECIAL_DBUS_SOCKET)) { + if (manager_unit_inactive_or_pending(m, SPECIAL_DBUS_SERVICE) || + manager_unit_inactive_or_pending(m, SPECIAL_DBUS_SOCKET)) { r = -EADDRNOTAVAIL; dbus_set_error(&error, BUS_ERROR_SHUTTING_DOWN, "Refusing activation, D-Bus is shutting down."); } else { @@ -406,7 +403,7 @@ static DBusHandlerResult api_bus_message_filter(DBusConnection *connection, DBus dbus_error_free(&error); if (reply) { - if (!dbus_connection_send(connection, reply, NULL)) + if (!bus_maybe_send_reply(connection, message, reply)) goto oom; dbus_message_unref(reply); @@ -455,7 +452,7 @@ static DBusHandlerResult system_bus_message_filter(DBusConnection *connection, D DBUS_TYPE_INVALID)) log_error("Failed to parse Released message: %s", bus_error_message(&error)); else - cgroup_notify_empty(m, cgroup); + manager_notify_cgroup_empty(m, cgroup); } dbus_error_free(&error); @@ -491,7 +488,7 @@ static DBusHandlerResult private_bus_message_filter(DBusConnection *connection, DBUS_TYPE_INVALID)) log_error("Failed to parse Released message: %s", bus_error_message(&error)); else - cgroup_notify_empty(m, cgroup); + manager_notify_cgroup_empty(m, cgroup); /* Forward the message to the system bus, so that user * instances are notified as well */ @@ -978,9 +975,8 @@ static DBusConnection* manager_bus_connect_private(Manager *m, DBusBusType type) } return connection; + fail: - if (connection) - dbus_connection_close(connection); dbus_error_free(&error); return NULL; } @@ -1054,7 +1050,7 @@ fail: static int bus_init_private(Manager *m) { DBusError error; int r; - const char *const external_only[] = { + static const char *const external_only[] = { "EXTERNAL", NULL }; @@ -1139,19 +1135,19 @@ int bus_init(Manager *m, bool try_bus_connect) { if (set_ensure_allocated(&m->bus_connections, trivial_hash_func, trivial_compare_func) < 0 || set_ensure_allocated(&m->bus_connections_for_dispatch, trivial_hash_func, trivial_compare_func) < 0) - goto oom; + return log_oom(); if (m->name_data_slot < 0) if (!dbus_pending_call_allocate_data_slot(&m->name_data_slot)) - goto oom; + return log_oom(); if (m->conn_data_slot < 0) if (!dbus_pending_call_allocate_data_slot(&m->conn_data_slot)) - goto oom; + return log_oom(); if (m->subscribed_data_slot < 0) if (!dbus_connection_allocate_data_slot(&m->subscribed_data_slot)) - goto oom; + return log_oom(); if (try_bus_connect) { if ((r = bus_init_system(m)) < 0 || @@ -1159,16 +1155,14 @@ int bus_init(Manager *m, bool try_bus_connect) { return r; } - if ((r = bus_init_private(m)) < 0) + r = bus_init_private(m); + if (r < 0) return r; return 0; -oom: - return log_oom(); } static void shutdown_connection(Manager *m, DBusConnection *c) { - Set *s; Job *j; Iterator i; @@ -1184,15 +1178,7 @@ static void shutdown_connection(Manager *m, DBusConnection *c) { set_remove(m->bus_connections, c); set_remove(m->bus_connections_for_dispatch, c); - - if ((s = BUS_CONNECTION_SUBSCRIBED(m, c))) { - char *t; - - while ((t = set_steal_first(s))) - free(t); - - set_free(s); - } + set_free_free(BUS_CONNECTION_SUBSCRIBED(m, c)); if (m->queued_message_connection == c) { m->queued_message_connection = NULL; @@ -1263,10 +1249,10 @@ void bus_done(Manager *m) { set_free(m->bus_connections_for_dispatch); if (m->name_data_slot >= 0) - dbus_pending_call_free_data_slot(&m->name_data_slot); + dbus_pending_call_free_data_slot(&m->name_data_slot); if (m->conn_data_slot >= 0) - dbus_pending_call_free_data_slot(&m->conn_data_slot); + dbus_pending_call_free_data_slot(&m->conn_data_slot); if (m->subscribed_data_slot >= 0) dbus_connection_free_data_slot(&m->subscribed_data_slot); @@ -1393,6 +1379,12 @@ bool bus_has_subscriber(Manager *m) { assert(m); + /* If we are reloading then we might not have deserialized the + subscribers yet, hence let's assume that there are some */ + + if (m->n_reloading > 0) + return true; + SET_FOREACH(c, m->bus_connections_for_dispatch, i) if (bus_connection_has_subscriber(m, c)) return true; @@ -1459,7 +1451,7 @@ void bus_broadcast_finished( usec_t userspace_usec, usec_t total_usec) { - DBusMessage *message; + _cleanup_dbus_message_unref_ DBusMessage *message = NULL; assert(m); @@ -1479,16 +1471,106 @@ void bus_broadcast_finished( DBUS_TYPE_UINT64, &total_usec, DBUS_TYPE_INVALID)) { log_oom(); - goto finish; + return; } if (bus_broadcast(m, message) < 0) { log_oom(); - goto finish; + return; + } +} + +void bus_broadcast_reloading(Manager *m, bool active) { + + _cleanup_dbus_message_unref_ DBusMessage *message = NULL; + dbus_bool_t b = active; + + assert(m); + + message = dbus_message_new_signal("/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "Reloading"); + if (!message) { + log_oom(); + return; } -finish: - if (message) - dbus_message_unref(message); + assert_cc(sizeof(usec_t) == sizeof(uint64_t)); + if (!dbus_message_append_args(message, + DBUS_TYPE_BOOLEAN, &b, + DBUS_TYPE_INVALID)) { + log_oom(); + return; + } + + + if (bus_broadcast(m, message) < 0) { + log_oom(); + return; + } +} + +Set *bus_acquire_subscribed(Manager *m, DBusConnection *c) { + Set *s; + + assert(m); + assert(c); + + s = BUS_CONNECTION_SUBSCRIBED(m, c); + if (s) + return s; + + s = set_new(string_hash_func, string_compare_func); + if (!s) + return NULL; + + if (!dbus_connection_set_data(c, m->subscribed_data_slot, s, NULL)) { + set_free(s); + return NULL; + } + + return s; +} + +void bus_serialize(Manager *m, FILE *f) { + char *client; + Iterator i; + Set *s; + + assert(m); + assert(f); + + if (!m->api_bus) + return; + + s = BUS_CONNECTION_SUBSCRIBED(m, m->api_bus); + SET_FOREACH(client, s, i) + fprintf(f, "subscribed=%s\n", client); +} + +int bus_deserialize_item(Manager *m, const char *line) { + const char *e; + char *b; + Set *s; + + assert(m); + assert(line); + + if (!m->api_bus) + return 0; + + e = startswith(line, "subscribed="); + if (!e) + return 0; + + s = bus_acquire_subscribed(m, m->api_bus); + if (!s) + return -ENOMEM; + + b = strdup(e); + if (!b) + return -ENOMEM; + + set_consume(s, b); + + return 1; }