chiark / gitweb /
core: serialize/deserialize bus subscribers
authorLennart Poettering <lennart@poettering.net>
Wed, 10 Jul 2013 17:24:03 +0000 (19:24 +0200)
committerLennart Poettering <lennart@poettering.net>
Wed, 10 Jul 2013 21:41:03 +0000 (23:41 +0200)
12 files changed:
src/core/dbus-manager.c
src/core/dbus.c
src/core/dbus.h
src/core/main.c
src/core/manager.c
src/core/manager.h
src/core/unit.c
src/login/logind-dbus.c
src/shared/set.c
src/test/test-engine.c
src/test/test-sched-prio.c
src/test/test-unit-name.c

index fe2f7498039147275b40ca98bc30503aca5417ef..742f6bbd8551eae824965606a3c54c40b0fe21a8 100644 (file)
@@ -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)
index c2097a4dbffb629c1274d1ed1915623b11d05141..5180d89b2ce84319af4a1f83d0fb20536c4f4ebf 100644 (file)
@@ -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;
+}
index c7a058e198357d240f8f2e2b50e24e98fc90808e..b5c28c6ab6f78f7e05738b0b06355759f18cd473 100644 (file)
@@ -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)
 
index 243855fa153e1a89a354d91aa1b81fb3667070f1..1d188e0bfe349a4b35952b38e80bdb0ef2af894e 100644 (file)
@@ -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;
index 612819442726341567174fd8f65fbe8f6fc4002c..51f03de0986f213d9955a290a6535d558d728245 100644 (file)
@@ -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);
         }
 
index 57a0a8d251ed2dd2081a4927a9dcceec1ed998c9..31da04e47c415d853a12cb2e69bad1021858070f 100644 (file)
@@ -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);
index 447f2015ab5b50315272d806a6c86e6717c6608e..70cdd3d943dbcabc91e38d63343793566fd1f77c 100644 (file)
@@ -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;
 
 
index eeff84394e4a9ca8bbc24f40c264c40696ac817e..29a196323bdde099736a48fc1f719203e0edecc7 100644 (file)
@@ -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;
index c338dc3a44c462176a96dce3c3e189c9c9afa9f4..5a4bf11bdfda45b01d4ef63ad9220c127c2daa99 100644 (file)
@@ -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;
 }
 
index 0f3862226a16124b43e5173e4d9a8f95bf3bac2b..20ae103a1907db708bcf264f26409d743597f2c5 100644 (file)
@@ -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);
index ba0aacf79dfe422147ee7d2514b34bbfa1902d8d..7af740757ac7c1868e4d9db31c256d1154403720 100644 (file)
@@ -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;
index 86cb2b8da64c42ecd75a9b1bf41ce1fa0c288a2c..93bf28aacee98acc9fae250e0e7a25ce63dfa13d 100644 (file)
@@ -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;