1
1
mirror of https://github.com/systemd/systemd-stable.git synced 2024-10-28 20:25:25 +03:00

logind: make sure to terminate systemd user on logouts

Currently if the user logs out, the GC may never call user_stop(),
this will not terminate the systemd user and (sd-pam) of that user.

To fix this, remove the USER_CLOSING state check that is blocking the
GC from calling user_stop(). Since if user_check_gc() returns false
this means that all the sessions of the user were removed which will
make user_get_state() return USER_CLOSING.

Conclusion: that test will never be statisfied.

So we remove the USER_CLOSING check and replace it with a check inside
user_stop() this way we know that user_stop() has already queued stop
jobs, no need to redo.

This ensures that the GC will get its two steps correctly as pointed out
by Lennart:
http://lists.freedesktop.org/archives/systemd-devel/2014-February/016825.html

Note: this also fixes another bug that prevents creating the user
private dbus socket which will break communications with the user
manager.
This commit is contained in:
Djalal Harouni 2014-02-13 18:31:43 +01:00 committed by Lennart Poettering
parent 24fb111207
commit b58b227a53
2 changed files with 9 additions and 2 deletions

View File

@ -499,6 +499,12 @@ int user_stop(User *u, bool force) {
int r = 0, k; int r = 0, k;
assert(u); assert(u);
/* Stop jobs have already been queued */
if (u->stopping) {
user_save(u);
return r;
}
LIST_FOREACH(sessions_by_user, s, u->sessions) { LIST_FOREACH(sessions_by_user, s, u->sessions) {
k = session_stop(s, force); k = session_stop(s, force);
if (k < 0) if (k < 0)

View File

@ -889,10 +889,11 @@ void manager_gc(Manager *m, bool drop_not_started) {
LIST_REMOVE(gc_queue, m->user_gc_queue, user); LIST_REMOVE(gc_queue, m->user_gc_queue, user);
user->in_gc_queue = false; user->in_gc_queue = false;
if (!user_check_gc(user, drop_not_started) && /* First step: queue stop jobs */
user_get_state(user) != USER_CLOSING) if (!user_check_gc(user, drop_not_started))
user_stop(user, false); user_stop(user, false);
/* Second step: finalize user */
if (!user_check_gc(user, drop_not_started)) { if (!user_check_gc(user, drop_not_started)) {
user_finalize(user); user_finalize(user);
user_free(user); user_free(user);