[systemd-devel] [PATCH 3/3] logind: differentiate between user state opening and closing
Djalal Harouni
tixxdz at opendz.org
Wed Jan 22 01:25:53 PST 2014
To get the state of the user, the user_get_state() is used.
This function will check if the user->slice_job or the user->service_job
are set then it will automatically return USER_OPENING. This is buggy
in the context of user closing:
At logout or D-Bus TerminateUser() calls user_stop()
user_stop()
=> session_stop() on sessions
=> session_stop_scope() on sessions
=> user_get_state() == USER_CLOSING or USER_ACTIVE or USER_ONLINE
(incorrect)
(depends on session closing execution and if we have finished the
session scope jobs or not, if all the scopes are being queued
then their session->scope_job will be set which means all
sessions are in the OPENING_STATE, so user state will be
USER_ONLINE).
The previous patch improves session_get_state() logic, and if
scopes are being queued then sessions are in SESSION_CLOSING state
which makes user_get_state() return USER_CLOSING.
At user_stop()
user_stop_slice() queues the slice and sets user->slice_job
user_stop_service() queue the service and sets user->service_job
=> user_get_state() == USER_OPENING (incorrect)
After the slice and service jobs are removed the state will be again
correct.
=> user_get_state() == USER_CLOSING (correct)
To fix this and make sure that the state will always be USER_CLOSING
we add a flag that is used to differentiate between USER_OPENING and
USER_CLOSING when 'slice_job' and 'service_job' are set.
The 'slice_opening' flag for 'user->slice_job' and 'service_opening'
for 'user->service_job' are set to true only during real user opening.
During user closing they are already in the false state.
Update user_get_state() to check if they are set if so this is
USER_OPENING, otherwise we are in the USER_CLOSING.
---
src/login/logind-dbus.c | 2 ++
src/login/logind-user.c | 5 ++++-
src/login/logind-user.h | 2 ++
3 files changed, 8 insertions(+), 1 deletion(-)
diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c
index 0123a34..a7452b1 100644
--- a/src/login/logind-dbus.c
+++ b/src/login/logind-dbus.c
@@ -2000,11 +2000,13 @@ int match_job_removed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_b
/* Clean this up after session_send_create_reply() */
free(user->service_job);
user->service_job = NULL;
+ user->service_opening = false;
}
if (streq_ptr(path, user->slice_job)) {
free(user->slice_job);
user->slice_job = NULL;
+ user->slice_opening = false;
}
user_save(user);
diff --git a/src/login/logind-user.c b/src/login/logind-user.c
index 0e46560..200763d 100644
--- a/src/login/logind-user.c
+++ b/src/login/logind-user.c
@@ -352,6 +352,7 @@ static int user_start_slice(User *u) {
free(u->slice_job);
u->slice_job = job;
+ u->slice_opening = true;
}
}
@@ -385,6 +386,7 @@ static int user_start_service(User *u) {
free(u->service_job);
u->service_job = job;
+ u->service_opening = true;
}
}
@@ -637,7 +639,8 @@ UserState user_get_state(User *u) {
assert(u);
- if (u->slice_job || u->service_job)
+ if ((u->slice_job && u->slice_opening) ||
+ (u->service_job && u->service_opening))
return USER_OPENING;
LIST_FOREACH(sessions_by_user, i, u->sessions) {
diff --git a/src/login/logind-user.h b/src/login/logind-user.h
index 0062880..ac43361 100644
--- a/src/login/logind-user.h
+++ b/src/login/logind-user.h
@@ -61,6 +61,8 @@ struct User {
bool in_gc_queue:1;
bool started:1;
+ bool service_opening:1; /* User service is being created */
+ bool slice_opening:1; /* User slice is being created */
LIST_HEAD(Session, sessions);
LIST_FIELDS(User, gc_queue);
--
1.8.3.1
More information about the systemd-devel
mailing list