X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Flogin%2Flogind-user.c;h=9dfead9d5d706213d690b4f66e3dda34fdfbe016;hp=27f78adae1a0e8824f26159fa1a518df9e6ed8e6;hb=2dc8f41a2bdcc25e6ec69a99cb6f34615cce59a5;hpb=5430f7f2bc7330f3088b894166bf3524a067e3d8 diff --git a/src/login/logind-user.c b/src/login/logind-user.c index 27f78adae..9dfead9d5 100644 --- a/src/login/logind-user.c +++ b/src/login/logind-user.c @@ -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); @@ -98,7 +100,7 @@ int user_save(User *u) { if (!u->started) return 0; - r = safe_mkdir("/run/systemd/users", 0755, 0, 0); + r = mkdir_safe_label("/run/systemd/users", 0755, 0, 0); if (r < 0) goto finish; @@ -137,40 +139,89 @@ int user_save(User *u) { if (u->sessions) { Session *i; + bool first; fputs("SESSIONS=", f); + first = true; LIST_FOREACH(sessions_by_user, i, u->sessions) { - fprintf(f, - "%s%c", - i->id, - i->sessions_by_user_next ? ' ' : '\n'); + if (first) + first = false; + else + fputc(' ', f); + + fputs(i->id, f); } - fputs("SEATS=", f); + fputs("\nSEATS=", f); + first = true; LIST_FOREACH(sessions_by_user, i, u->sessions) { - if (i->seat) - fprintf(f, - "%s%c", - i->seat->id, - i->sessions_by_user_next ? ' ' : '\n'); + if (!i->seat) + continue; + + if (first) + first = false; + else + fputc(' ', f); + + fputs(i->seat->id, f); } - fputs("ACTIVE_SESSIONS=", f); - LIST_FOREACH(sessions_by_user, i, u->sessions) - if (session_is_active(i)) - fprintf(f, - "%lu%c", - (unsigned long) i->user->uid, - i->sessions_by_user_next ? ' ' : '\n'); + fputs("\nACTIVE_SESSIONS=", f); + first = true; + LIST_FOREACH(sessions_by_user, i, u->sessions) { + if (!session_is_active(i)) + continue; + + if (first) + first = false; + else + fputc(' ', f); - fputs("ACTIVE_SEATS=", f); + fputs(i->id, f); + } + + fputs("\nONLINE_SESSIONS=", f); + first = true; LIST_FOREACH(sessions_by_user, i, u->sessions) { - if (session_is_active(i) && i->seat) - fprintf(f, - "%s%c", - i->seat->id, - i->sessions_by_user_next ? ' ' : '\n'); + if (session_get_state(i) == SESSION_CLOSING) + continue; + + if (first) + first = false; + else + fputc(' ', f); + + fputs(i->id, f); } + + fputs("\nACTIVE_SEATS=", f); + first = true; + LIST_FOREACH(sessions_by_user, i, u->sessions) { + if (!session_is_active(i) || !i->seat) + continue; + + if (first) + first = false; + else + fputc(' ', f); + + fputs(i->seat->id, f); + } + + fputs("\nONLINE_SEATS=", f); + first = true; + LIST_FOREACH(sessions_by_user, i, u->sessions) { + if (session_get_state(i) == SESSION_CLOSING || !i->seat) + continue; + + if (first) + first = false; + else + fputc(' ', f); + + fputs(i->seat->id, f); + } + fputc('\n', f); } fflush(f); @@ -231,23 +282,19 @@ static int user_mkdir_runtime_path(User *u) { assert(u); - r = safe_mkdir("/run/user", 0755, 0, 0); + r = mkdir_safe_label("/run/user", 0755, 0, 0); if (r < 0) { log_error("Failed to create /run/user: %s", strerror(-r)); return r; } if (!u->runtime_path) { - p = strappend("/run/user/", u->name); - - if (!p) { - log_error("Out of memory"); - return -ENOMEM; - } + if (asprintf(&p, "/run/user/%lu", (unsigned long) u->uid) < 0) + return log_oom(); } else p = u->runtime_path; - r = safe_mkdir(p, 0700, u->uid, u->gid); + r = mkdir_safe_label(p, 0700, u->uid, u->gid); if (r < 0) { log_error("Failed to create runtime directory %s: %s", p, strerror(-r)); free(p); @@ -267,10 +314,8 @@ static int user_create_cgroup(User *u) { assert(u); if (!u->cgroup_path) { - if (asprintf(&p, "%s/%s", u->manager->cgroup_path, u->name) < 0) { - log_error("Out of memory"); - return -ENOMEM; - } + if (asprintf(&p, "%s/%s", u->manager->cgroup_path, u->name) < 0) + return log_oom(); } else p = u->cgroup_path; @@ -294,6 +339,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; } @@ -398,6 +445,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; @@ -498,9 +547,21 @@ int user_get_idle_hint(User *u, dual_timestamp *t) { return idle_hint; } +static int user_check_linger_file(User *u) { + char *p; + int r; + + if (asprintf(&p, "/var/lib/systemd/linger/%s", u->name) < 0) + return -ENOMEM; + + r = access(p, F_OK) >= 0; + free(p); + + return r; +} + int user_check_gc(User *u, bool drop_not_started) { int r; - char *p; assert(u); @@ -510,13 +571,7 @@ int user_check_gc(User *u, bool drop_not_started) { if (u->sessions) return 1; - if (asprintf(&p, "/var/lib/systemd/linger/%s", u->name) < 0) - return -ENOMEM; - - r = access(p, F_OK) >= 0; - free(p); - - if (r > 0) + if (user_check_linger_file(u) > 0) return 1; if (u->cgroup_path) { @@ -543,17 +598,25 @@ void user_add_to_gc_queue(User *u) { UserState user_get_state(User *u) { Session *i; + bool all_closing = true; assert(u); - if (!u->sessions) - return USER_LINGERING; - LIST_FOREACH(sessions_by_user, i, u->sessions) + LIST_FOREACH(sessions_by_user, i, u->sessions) { if (session_is_active(i)) return USER_ACTIVE; + if (session_get_state(i) != SESSION_CLOSING) + all_closing = false; + } + + if (u->sessions) + return all_closing ? USER_CLOSING : USER_ONLINE; + + if (user_check_linger_file(u) > 0) + return USER_LINGERING; - return USER_ONLINE; + return USER_CLOSING; } int user_kill(User *u, int signo) { @@ -584,7 +647,8 @@ static const char* const user_state_table[_USER_STATE_MAX] = { [USER_OFFLINE] = "offline", [USER_LINGERING] = "lingering", [USER_ONLINE] = "online", - [USER_ACTIVE] = "active" + [USER_ACTIVE] = "active", + [USER_CLOSING] = "closing" }; DEFINE_STRING_TABLE_LOOKUP(user_state, UserState);