core: serialize/deserialize bus subscribers
This commit is contained in:
parent
376dd21dc0
commit
6fa4853328
|
@ -1057,18 +1057,10 @@ 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);
|
||||
s = bus_acquire_subscribed(m, connection);
|
||||
if (!s)
|
||||
goto oom;
|
||||
|
||||
if (!dbus_connection_set_data(connection, m->subscribed_data_slot, s, NULL)) {
|
||||
set_free(s);
|
||||
goto oom;
|
||||
}
|
||||
}
|
||||
|
||||
client = strdup(bus_message_get_sender_with_fallback(message));
|
||||
if (!client)
|
||||
goto oom;
|
||||
|
|
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue