From: Lennart Poettering Date: Wed, 10 Jul 2013 17:24:03 +0000 (+0200) Subject: core: serialize/deserialize bus subscribers X-Git-Tag: v206~165 X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=commitdiff_plain;h=6fa4853328e3d78d092172fa54effb7e785d0a85 core: serialize/deserialize bus subscribers --- diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c index fe2f74980..742f6bbd8 100644 --- a/src/core/dbus-manager.c +++ b/src/core/dbus-manager.c @@ -1057,17 +1057,9 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection, SELINUX_ACCESS_CHECK(connection, message, "status"); - s = BUS_CONNECTION_SUBSCRIBED(m, connection); - if (!s) { - s = set_new(string_hash_func, string_compare_func); - if (!s) - goto oom; - - if (!dbus_connection_set_data(connection, m->subscribed_data_slot, s, NULL)) { - set_free(s); - goto oom; - } - } + s = bus_acquire_subscribed(m, connection); + if (!s) + goto oom; client = strdup(bus_message_get_sender_with_fallback(message)); if (!client) diff --git a/src/core/dbus.c b/src/core/dbus.c index c2097a4db..5180d89b2 100644 --- a/src/core/dbus.c +++ b/src/core/dbus.c @@ -1135,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 || @@ -1155,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; @@ -1180,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; @@ -1259,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); @@ -1488,3 +1478,69 @@ finish: if (message) dbus_message_unref(message); } + +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; +} diff --git a/src/core/dbus.h b/src/core/dbus.h index c7a058e19..b5c28c6ab 100644 --- a/src/core/dbus.h +++ b/src/core/dbus.h @@ -44,6 +44,11 @@ int bus_fdset_add_all(Manager *m, FDSet *fds); void bus_broadcast_finished(Manager *m, usec_t firmware_usec, usec_t loader_usec, usec_t kernel_usec, usec_t initrd_usec, usec_t userspace_usec, usec_t total_usec); +Set *bus_acquire_subscribed(Manager *m, DBusConnection *c); + +void bus_serialize(Manager *m, FILE *f); +int bus_deserialize_item(Manager *m, const char *line); + #define BUS_CONNECTION_SUBSCRIBED(m, c) dbus_connection_get_data((c), (m)->subscribed_data_slot) #define BUS_PENDING_CALL_NAME(m, p) dbus_pending_call_get_data((p), (m)->name_data_slot) diff --git a/src/core/main.c b/src/core/main.c index 243855fa1..1d188e0bf 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -1613,7 +1613,7 @@ int main(int argc, char *argv[]) { if (arg_running_as == SYSTEMD_SYSTEM) bump_rlimit_nofile(&saved_rlimit_nofile); - r = manager_new(arg_running_as, &m); + r = manager_new(arg_running_as, !!serialization, &m); if (r < 0) { log_error("Failed to allocate manager object: %s", strerror(-r)); goto finish; diff --git a/src/core/manager.c b/src/core/manager.c index 612819442..51f03de09 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -424,7 +424,7 @@ static void manager_strip_environment(Manager *m) { strv_env_clean(m->environment); } -int manager_new(SystemdRunningAs running_as, Manager **_m) { +int manager_new(SystemdRunningAs running_as, bool reexecuting, Manager **_m) { Manager *m; int r = -ENOMEM; @@ -476,7 +476,8 @@ int manager_new(SystemdRunningAs running_as, Manager **_m) { if (!m->cgroup_unit) goto fail; - if (!(m->watch_bus = hashmap_new(string_hash_func, string_compare_func))) + m->watch_bus = hashmap_new(string_hash_func, string_compare_func); + if (!m->watch_bus) goto fail; m->epoll_fd = epoll_create1(EPOLL_CLOEXEC); @@ -502,7 +503,7 @@ int manager_new(SystemdRunningAs running_as, Manager **_m) { /* Try to connect to the busses, if possible. */ if ((running_as == SYSTEMD_USER && getenv("DBUS_SESSION_BUS_ADDRESS")) || running_as == SYSTEMD_SYSTEM) { - r = bus_init(m, running_as != SYSTEMD_SYSTEM); + r = bus_init(m, reexecuting || running_as != SYSTEMD_SYSTEM); if (r < 0) goto fail; } else @@ -2041,6 +2042,8 @@ int manager_serialize(Manager *m, FILE *f, FDSet *fds, bool switching_root) { } } + bus_serialize(m, f); + fputc('\n', f); HASHMAP_FOREACH_KEY(u, t, m->units, i) { @@ -2054,7 +2057,8 @@ int manager_serialize(Manager *m, FILE *f, FDSet *fds, bool switching_root) { fputs(u->id, f); fputc('\n', f); - if ((r = unit_serialize(u, f, fds, !switching_root)) < 0) { + r = unit_serialize(u, f, fds, !switching_root); + if (r < 0) { m->n_reloading --; return r; } @@ -2159,7 +2163,7 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) { strv_free(m->environment); m->environment = e; - } else + } else if (bus_deserialize_item(m, l) == 0) log_debug("Unknown serialization item '%s'", l); } diff --git a/src/core/manager.h b/src/core/manager.h index 57a0a8d25..31da04e47 100644 --- a/src/core/manager.h +++ b/src/core/manager.h @@ -248,7 +248,7 @@ struct Manager { char *switch_root_init; }; -int manager_new(SystemdRunningAs running_as, Manager **m); +int manager_new(SystemdRunningAs running_as, bool reexecuting, Manager **m); void manager_free(Manager *m); int manager_enumerate(Manager *m); diff --git a/src/core/unit.c b/src/core/unit.c index 447f2015a..70cdd3d94 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -2128,7 +2128,8 @@ int unit_serialize(Unit *u, FILE *f, FDSet *fds, bool serialize_jobs) { if (!unit_can_serialize(u)) return 0; - if ((r = UNIT_VTABLE(u)->serialize(u, f, fds)) < 0) + r = UNIT_VTABLE(u)->serialize(u, f, fds); + if (r < 0) return r; diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c index eeff84394..29a196323 100644 --- a/src/login/logind-dbus.c +++ b/src/login/logind-dbus.c @@ -2411,6 +2411,7 @@ DBusHandlerResult bus_message_filter( if (u) user_add_to_gc_queue(u); } + } else if (dbus_message_is_signal(message, "org.freedesktop.systemd1.Manager", "UnitRemoved")) { const char *path, *unit; diff --git a/src/shared/set.c b/src/shared/set.c index c338dc3a4..5a4bf11bd 100644 --- a/src/shared/set.c +++ b/src/shared/set.c @@ -50,9 +50,12 @@ int set_put(Set *s, void *value) { } int set_consume(Set *s, void *value) { - int r = set_put(s, value); + int r; + + r = set_put(s, value); if (r < 0) free(value); + return r; } diff --git a/src/test/test-engine.c b/src/test/test-engine.c index 0f3862226..20ae103a1 100644 --- a/src/test/test-engine.c +++ b/src/test/test-engine.c @@ -33,7 +33,7 @@ int main(int argc, char *argv[]) { assert_se(set_unit_path("test") >= 0); - assert_se(manager_new(SYSTEMD_SYSTEM, &m) >= 0); + assert_se(manager_new(SYSTEMD_SYSTEM, false, &m) >= 0); printf("Load1:\n"); assert_se(manager_load_unit(m, "a.service", NULL, NULL, &a) >= 0); diff --git a/src/test/test-sched-prio.c b/src/test/test-sched-prio.c index ba0aacf79..7af740757 100644 --- a/src/test/test-sched-prio.c +++ b/src/test/test-sched-prio.c @@ -34,7 +34,7 @@ int main(int argc, char *argv[]) { /* prepare the test */ assert_se(set_unit_path(TEST_DIR) >= 0); - r = manager_new(SYSTEMD_USER, &m); + r = manager_new(SYSTEMD_USER, false, &m); if (r == -EPERM) { puts("manager_new: Permission denied. Skipping test."); return EXIT_TEST_SKIP; diff --git a/src/test/test-unit-name.c b/src/test/test-unit-name.c index 86cb2b8da..93bf28aac 100644 --- a/src/test/test-unit-name.c +++ b/src/test/test-unit-name.c @@ -123,7 +123,7 @@ static int test_unit_printf(void) { assert_se((root = getpwnam("root"))); assert_se(asprintf(&root_uid, "%d", (int) root->pw_uid) > 0); - r = manager_new(SYSTEMD_USER, &m); + r = manager_new(SYSTEMD_USER, false, &m); if (r == -EPERM) { puts("manager_new: Permission denied. Skipping test."); return EXIT_TEST_SKIP;