logind: properly clean up user cgroups when they run empty
This commit is contained in:
@@ -88,7 +88,7 @@ void session_free(Session *s) {
|
||||
}
|
||||
|
||||
if (s->cgroup_path)
|
||||
hashmap_remove(s->manager->cgroups, s->cgroup_path);
|
||||
hashmap_remove(s->manager->session_cgroups, s->cgroup_path);
|
||||
|
||||
free(s->cgroup_path);
|
||||
strv_free(s->controllers);
|
||||
@@ -527,7 +527,7 @@ static int session_create_cgroup(Session *s) {
|
||||
}
|
||||
}
|
||||
|
||||
hashmap_put(s->manager->cgroups, s->cgroup_path, s);
|
||||
hashmap_put(s->manager->session_cgroups, s->cgroup_path, s);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -646,7 +646,7 @@ static int session_terminate_cgroup(Session *s) {
|
||||
STRV_FOREACH(k, s->user->manager->controllers)
|
||||
cg_trim(*k, s->cgroup_path, true);
|
||||
|
||||
hashmap_remove(s->manager->cgroups, s->cgroup_path);
|
||||
hashmap_remove(s->manager->session_cgroups, s->cgroup_path);
|
||||
|
||||
free(s->cgroup_path);
|
||||
s->cgroup_path = NULL;
|
||||
|
||||
@@ -75,6 +75,8 @@ void user_free(User *u) {
|
||||
while (u->sessions)
|
||||
session_free(u->sessions);
|
||||
|
||||
if (u->cgroup_path)
|
||||
hashmap_remove(u->manager->user_cgroups, u->cgroup_path);
|
||||
free(u->cgroup_path);
|
||||
|
||||
free(u->service);
|
||||
@@ -313,6 +315,8 @@ static int user_create_cgroup(User *u) {
|
||||
log_warning("Failed to create cgroup %s:%s: %s", *k, p, strerror(-r));
|
||||
}
|
||||
|
||||
hashmap_put(u->manager->user_cgroups, u->cgroup_path, u);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -417,6 +421,8 @@ static int user_terminate_cgroup(User *u) {
|
||||
STRV_FOREACH(k, u->manager->controllers)
|
||||
cg_trim(*k, u->cgroup_path, true);
|
||||
|
||||
hashmap_remove(u->manager->user_cgroups, u->cgroup_path);
|
||||
|
||||
free(u->cgroup_path);
|
||||
u->cgroup_path = NULL;
|
||||
|
||||
|
||||
+57
-8
@@ -64,13 +64,16 @@ Manager *manager_new(void) {
|
||||
m->inhibitors = hashmap_new(string_hash_func, string_compare_func);
|
||||
m->buttons = hashmap_new(string_hash_func, string_compare_func);
|
||||
|
||||
m->cgroups = hashmap_new(string_hash_func, string_compare_func);
|
||||
m->user_cgroups = hashmap_new(string_hash_func, string_compare_func);
|
||||
m->session_cgroups = hashmap_new(string_hash_func, string_compare_func);
|
||||
|
||||
m->session_fds = hashmap_new(trivial_hash_func, trivial_compare_func);
|
||||
m->inhibitor_fds = hashmap_new(trivial_hash_func, trivial_compare_func);
|
||||
m->button_fds = hashmap_new(trivial_hash_func, trivial_compare_func);
|
||||
|
||||
if (!m->devices || !m->seats || !m->sessions || !m->users || !m->inhibitors || !m->buttons ||
|
||||
!m->cgroups || !m->session_fds || !m->inhibitor_fds || !m->button_fds) {
|
||||
!m->user_cgroups || !m->session_cgroups ||
|
||||
!m->session_fds || !m->inhibitor_fds || !m->button_fds) {
|
||||
manager_free(m);
|
||||
return NULL;
|
||||
}
|
||||
@@ -131,7 +134,9 @@ void manager_free(Manager *m) {
|
||||
hashmap_free(m->inhibitors);
|
||||
hashmap_free(m->buttons);
|
||||
|
||||
hashmap_free(m->cgroups);
|
||||
hashmap_free(m->user_cgroups);
|
||||
hashmap_free(m->session_cgroups);
|
||||
|
||||
hashmap_free(m->session_fds);
|
||||
hashmap_free(m->inhibitor_fds);
|
||||
hashmap_free(m->button_fds);
|
||||
@@ -1008,7 +1013,7 @@ int manager_get_session_by_cgroup(Manager *m, const char *cgroup, Session **sess
|
||||
assert(cgroup);
|
||||
assert(session);
|
||||
|
||||
s = hashmap_get(m->cgroups, cgroup);
|
||||
s = hashmap_get(m->session_cgroups, cgroup);
|
||||
if (s) {
|
||||
*session = s;
|
||||
return 1;
|
||||
@@ -1032,7 +1037,7 @@ int manager_get_session_by_cgroup(Manager *m, const char *cgroup, Session **sess
|
||||
|
||||
*e = 0;
|
||||
|
||||
s = hashmap_get(m->cgroups, p);
|
||||
s = hashmap_get(m->session_cgroups, p);
|
||||
if (s) {
|
||||
free(p);
|
||||
*session = s;
|
||||
@@ -1041,6 +1046,47 @@ int manager_get_session_by_cgroup(Manager *m, const char *cgroup, Session **sess
|
||||
}
|
||||
}
|
||||
|
||||
int manager_get_user_by_cgroup(Manager *m, const char *cgroup, User **user) {
|
||||
User *u;
|
||||
char *p;
|
||||
|
||||
assert(m);
|
||||
assert(cgroup);
|
||||
assert(user);
|
||||
|
||||
u = hashmap_get(m->user_cgroups, cgroup);
|
||||
if (u) {
|
||||
*user = u;
|
||||
return 1;
|
||||
}
|
||||
|
||||
p = strdup(cgroup);
|
||||
if (!p) {
|
||||
log_error("Out of memory.");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
char *e;
|
||||
|
||||
e = strrchr(p, '/');
|
||||
if (!e || e == p) {
|
||||
free(p);
|
||||
*user = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
*e = 0;
|
||||
|
||||
u = hashmap_get(m->user_cgroups, p);
|
||||
if (u) {
|
||||
free(p);
|
||||
*user = u;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int manager_get_session_by_pid(Manager *m, pid_t pid, Session **session) {
|
||||
char *p;
|
||||
int r;
|
||||
@@ -1061,13 +1107,16 @@ int manager_get_session_by_pid(Manager *m, pid_t pid, Session **session) {
|
||||
|
||||
void manager_cgroup_notify_empty(Manager *m, const char *cgroup) {
|
||||
Session *s;
|
||||
User *u;
|
||||
int r;
|
||||
|
||||
r = manager_get_session_by_cgroup(m, cgroup, &s);
|
||||
if (r <= 0)
|
||||
return;
|
||||
if (r > 0)
|
||||
session_add_to_gc_queue(s);
|
||||
|
||||
session_add_to_gc_queue(s);
|
||||
r = manager_get_user_by_cgroup(m, cgroup, &u);
|
||||
if (r > 0)
|
||||
user_add_to_gc_queue(u);
|
||||
}
|
||||
|
||||
static void manager_dispatch_other(Manager *m, int fd) {
|
||||
|
||||
+4
-1
@@ -81,7 +81,9 @@ struct Manager {
|
||||
unsigned long session_counter;
|
||||
unsigned long inhibit_counter;
|
||||
|
||||
Hashmap *cgroups;
|
||||
Hashmap *session_cgroups;
|
||||
Hashmap *user_cgroups;
|
||||
|
||||
Hashmap *session_fds;
|
||||
Hashmap *inhibitor_fds;
|
||||
Hashmap *button_fds;
|
||||
@@ -146,6 +148,7 @@ void manager_gc(Manager *m, bool drop_not_started);
|
||||
|
||||
int manager_get_idle_hint(Manager *m, dual_timestamp *t);
|
||||
|
||||
int manager_get_user_by_cgroup(Manager *m, const char *cgroup, User **user);
|
||||
int manager_get_session_by_cgroup(Manager *m, const char *cgroup, Session **session);
|
||||
int manager_get_session_by_pid(Manager *m, pid_t pid, Session **session);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user