summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2013-07-10 19:24:03 +0200
committerLennart Poettering <lennart@poettering.net>2013-07-10 23:41:03 +0200
commit6fa4853328e3d78d092172fa54effb7e785d0a85 (patch)
treedf7ec622c6f825f6470be62f49dfcaac2d020e71
parent376dd21dc0757e8a6d3f60d6d21bb802a90f1983 (diff)
core: serialize/deserialize bus subscribers
-rw-r--r--src/core/dbus-manager.c14
-rw-r--r--src/core/dbus.c94
-rw-r--r--src/core/dbus.h5
-rw-r--r--src/core/main.c2
-rw-r--r--src/core/manager.c14
-rw-r--r--src/core/manager.h2
-rw-r--r--src/core/unit.c3
-rw-r--r--src/login/logind-dbus.c1
-rw-r--r--src/shared/set.c5
-rw-r--r--src/test/test-engine.c2
-rw-r--r--src/test/test-sched-prio.c2
-rw-r--r--src/test/test-unit-name.c2
12 files changed, 104 insertions, 42 deletions
diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c
index fe2f749803..742f6bbd85 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 c2097a4dbf..5180d89b2c 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 c7a058e198..b5c28c6ab6 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 243855fa15..1d188e0bfe 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 6128194427..51f03de098 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 57a0a8d251..31da04e47c 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 447f2015ab..70cdd3d943 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 eeff84394e..29a196323b 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 c338dc3a44..5a4bf11bdf 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 0f3862226a..20ae103a19 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 ba0aacf79d..7af740757a 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 86cb2b8da6..93bf28aace 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;