summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSven Eden <yamakuzure@gmx.net>2017-01-26 09:56:23 +0100
committerSven Eden <yamakuzure@gmx.net>2017-03-14 10:23:10 +0100
commitdb74dfab5842da3f83d3bb9e2fa3bf8736939ecf (patch)
treef33a44512dea72f0dd475c98d19a1cb223b36e26
parentfaf2e887be42215c1999950d16d1975e70bbdfe9 (diff)
Remove dependency of systemd units, services and slices for new sessions.
* elogind does not support systemd services and units. But at least the units are needed to support the systemd cgroup slice/scope system. * Remove systemd subscription to scope, service and slice jobs. These can not be supported in any way, as they depend on systemd running the machine. * The functions session_start_scope(), user_start_service() and user_start_slice() no longer try to call systemd via dbus for assistance. This way they generate their proper scope, service and slice names, and store them in the Managers HashMaps for session and user units. This should enable us to reverse track pids to users and such stuff, as that is what systemd-logind does, not knowing whether any unit *really* has been started or not. However, this will not work out of the box until we find a way to integrate cg_create_everywhere() into elogind without becoming dependent of systemd unit, service and job knowledge again.
-rw-r--r--src/login/logind-dbus.c18
-rw-r--r--src/login/logind-session-dbus.c3
-rw-r--r--src/login/logind-session.c43
-rw-r--r--src/login/logind-session.h4
-rw-r--r--src/login/logind-user.c184
-rw-r--r--src/login/logind-user.h6
-rw-r--r--src/login/logind.h14
7 files changed, 210 insertions, 62 deletions
diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c
index fdf95fc50..31580af52 100644
--- a/src/login/logind-dbus.c
+++ b/src/login/logind-dbus.c
@@ -821,6 +821,15 @@ static int method_create_session(sd_bus_message *message, void *userdata, sd_bus
* created. We send the reply back from
* session_send_create_reply(). */
+ /* Elogind note: replying directly, since we're not actually
+ starting slices and thus we aren't waiting on systemd. */
+
+ r = session_send_create_reply(session, NULL);
+ if (r < 0)
+ goto fail;
+
+ session_save(session);
+
return 1;
fail:
@@ -2568,8 +2577,11 @@ int match_job_removed(sd_bus_message *message, void *userdata, sd_bus_error *err
session = hashmap_get(m->session_units, unit);
if (session) {
+/// elogind does not support scope jobs
+#if 0
if (streq_ptr(path, session->scope_job))
session->scope_job = mfree(session->scope_job);
+#endif // 0
session_jobs_reply(session, unit, result);
@@ -2580,11 +2592,14 @@ int match_job_removed(sd_bus_message *message, void *userdata, sd_bus_error *err
user = hashmap_get(m->user_units, unit);
if (user) {
+/// elogind does not support slice and service jobs
+#if 0
if (streq_ptr(path, user->service_job))
user->service_job = mfree(user->service_job);
if (streq_ptr(path, user->slice_job))
user->slice_job = mfree(user->slice_job);
+#endif // 0
LIST_FOREACH(sessions_by_user, session, user->sessions)
session_jobs_reply(session, unit, result);
@@ -2698,6 +2713,8 @@ int manager_send_changed(Manager *manager, const char *property, ...) {
l);
}
+/// UNNEEDED by elogind
+#if 0
int manager_start_scope(
Manager *manager,
const char *scope,
@@ -3015,3 +3032,4 @@ int manager_job_is_active(Manager *manager, const char *path) {
return true;
}
+#endif //
diff --git a/src/login/logind-session-dbus.c b/src/login/logind-session-dbus.c
index e6b4ccd7c..b0db8e2cc 100644
--- a/src/login/logind-session-dbus.c
+++ b/src/login/logind-session-dbus.c
@@ -704,8 +704,11 @@ int session_send_create_reply(Session *s, sd_bus_error *error) {
if (!s->create_message)
return 0;
+/// elogind does not support scope and service jobs
+#if 0
if (!sd_bus_error_is_set(error) && (s->scope_job || s->user->service_job))
return 0;
+#endif // 0
c = s->create_message;
s->create_message = NULL;
diff --git a/src/login/logind-session.c b/src/login/logind-session.c
index a277cda48..1a3567194 100644
--- a/src/login/logind-session.c
+++ b/src/login/logind-session.c
@@ -125,7 +125,10 @@ void session_free(Session *s) {
free(s->scope);
}
+/// elogind does not support systemd scope_jobs
+#if 0
free(s->scope_job);
+#endif // 0
sd_bus_message_unref(s->create_message);
@@ -196,8 +199,11 @@ int session_save(Session *s) {
if (s->scope)
fprintf(f, "SCOPE=%s\n", s->scope);
+/// elogind does not support systemd scope_jobs
+#if 0
if (s->scope_job)
fprintf(f, "SCOPE_JOB=%s\n", s->scope_job);
+#endif // 0
if (s->fifo_path)
fprintf(f, "FIFO=%s\n", s->fifo_path);
@@ -324,7 +330,10 @@ int session_load(Session *s) {
r = parse_env_file(s->state_file, NEWLINE,
"REMOTE", &remote,
"SCOPE", &s->scope,
+/// elogind does not support systemd scope_jobs
+#if 0
"SCOPE_JOB", &s->scope_job,
+#endif // 0
"FIFO", &s->fifo_path,
"SEAT", &seat,
"TTY", &s->tty,
@@ -500,7 +509,7 @@ int session_activate(Session *s) {
}
static int session_start_scope(Session *s) {
- int r;
+ int r = 0;
assert(s);
assert(s->user);
@@ -509,7 +518,7 @@ static int session_start_scope(Session *s) {
if (!s->scope) {
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_free_ char *description = NULL;
- char *scope, *job = NULL;
+ char *scope = NULL; //, *job = NULL;
description = strjoin("Session ", s->id, " of user ", s->user->name, NULL);
if (!description)
@@ -519,7 +528,10 @@ static int session_start_scope(Session *s) {
if (!scope)
return log_oom();
+/// elogind : Do not try to use dbus to call systemd
+#if 0
r = manager_start_scope(s->manager, scope, s->leader, s->user->slice, description, "logind.service", "systemd-user-sessions.service", &error, &job);
+#endif // 0
if (r < 0) {
log_error("Failed to start session scope %s: %s %s",
scope, bus_error_message(&error, r), error.name);
@@ -527,9 +539,11 @@ static int session_start_scope(Session *s) {
return r;
} else {
s->scope = scope;
-
+/// elogind does not support scope jobs
+#if 0
free(s->scope_job);
s->scope_job = job;
+#endif // 0
}
}
@@ -596,6 +610,8 @@ int session_start(Session *s) {
return 0;
}
+/// UNNEEDED by elogind
+#if 0
static int session_stop_scope(Session *s, bool force) {
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
char *job = NULL;
@@ -625,9 +641,10 @@ static int session_stop_scope(Session *s, bool force) {
return 0;
}
+#endif // 0
int session_stop(Session *s, bool force) {
- int r;
+ int r = 0;
assert(s);
@@ -643,7 +660,12 @@ int session_stop(Session *s, bool force) {
session_remove_fifo(s);
/* Kill cgroup */
+/// @todo : Currently elogind does not start scopes. It remains to be seen
+/// whether this is really not needed, but then, elogind is not a
+/// systemd cgroups manager.
+#if 0
r = session_stop_scope(s, force);
+#endif // 0
s->stopping = true;
@@ -932,11 +954,14 @@ bool session_check_gc(Session *s, bool drop_not_started) {
return true;
}
+/// elogind supports neither scopes nor jobs
+#if 0
if (s->scope_job && manager_job_is_active(s->manager, s->scope_job))
return true;
if (s->scope && manager_unit_is_active(s->manager, s->scope))
return true;
+#endif // 0
return false;
}
@@ -958,7 +983,12 @@ SessionState session_get_state(Session *s) {
if (s->stopping || s->timer_event_source)
return SESSION_CLOSING;
+/// elogind does not support systemd scope_jobs
+#if 0
if (s->scope_job || s->fifo_fd < 0)
+#else
+ if (s->fifo_fd < 0)
+#endif // 0
return SESSION_OPENING;
if (session_is_active(s))
@@ -970,10 +1000,15 @@ SessionState session_get_state(Session *s) {
int session_kill(Session *s, KillWho who, int signo) {
assert(s);
+/// FIXME: Without direct cgroup support, elogind can not kill sessions
+#if 0
if (!s->scope)
return -ESRCH;
return manager_kill_unit(s->manager, s->scope, who, signo, NULL);
+#else
+ return -ESRCH;
+#endif // 0
}
static int session_open_vt(Session *s) {
diff --git a/src/login/logind-session.h b/src/login/logind-session.h
index d054c33ce..202446833 100644
--- a/src/login/logind-session.h
+++ b/src/login/logind-session.h
@@ -89,8 +89,12 @@ struct Session {
char *service;
char *desktop;
+ /* always NULL */
char *scope;
+/// UNNEEDED (and unsupported) by elogind
+#if 0
char *scope_job;
+#endif // 0
Seat *seat;
unsigned int vtnr;
diff --git a/src/login/logind-user.c b/src/login/logind-user.c
index 987244e27..2733117c6 100644
--- a/src/login/logind-user.c
+++ b/src/login/logind-user.c
@@ -36,9 +36,10 @@
#include "bus-error.h"
#include "conf-parser.h"
#include "clean-ipc.h"
-#include "logind-user.h"
#include "smack-util.h"
#include "formats-util.h"
+#include "label.h"
+#include "logind-user.h"
User* user_new(Manager *m, uid_t uid, gid_t gid, const char *name) {
User *u;
@@ -93,8 +94,11 @@ void user_free(User *u) {
free(u->service);
}
+/// elogind does not support slice and service jobs
+#if 0
free(u->slice_job);
free(u->service_job);
+#endif // 0
free(u->runtime_path);
@@ -105,7 +109,7 @@ void user_free(User *u) {
free(u);
}
-int user_save(User *u) {
+static int user_save_internal(User *u) {
_cleanup_free_ char *temp_path = NULL;
_cleanup_fclose_ FILE *f = NULL;
int r;
@@ -113,9 +117,6 @@ int user_save(User *u) {
assert(u);
assert(u->state_file);
- if (!u->started)
- return 0;
-
r = mkdir_safe_label("/run/systemd/users", 0755, 0, 0);
if (r < 0)
goto fail;
@@ -138,13 +139,19 @@ int user_save(User *u) {
if (u->service)
fprintf(f, "SERVICE=%s\n", u->service);
+/// elogind does not support service jobs
+#if 0
if (u->service_job)
fprintf(f, "SERVICE_JOB=%s\n", u->service_job);
+#endif // 0
if (u->slice)
fprintf(f, "SLICE=%s\n", u->slice);
+/// elogind does not support slice jobs
+#if 0
if (u->slice_job)
fprintf(f, "SLICE_JOB=%s\n", u->slice_job);
+#endif // 0
if (u->display)
fprintf(f, "DISPLAY=%s\n", u->display->id);
@@ -263,6 +270,15 @@ fail:
return log_error_errno(r, "Failed to save user data %s: %m", u->state_file);
}
+int user_save(User *u) {
+ assert(u);
+
+ if (!u->started)
+ return 0;
+
+ return user_save_internal (u);
+}
+
int user_load(User *u) {
_cleanup_free_ char *display = NULL, *realtime = NULL, *monotonic = NULL;
Session *s = NULL;
@@ -273,9 +289,15 @@ int user_load(User *u) {
r = parse_env_file(u->state_file, NEWLINE,
"RUNTIME", &u->runtime_path,
"SERVICE", &u->service,
+/// elogind does not support service jobs
+#if 0
"SERVICE_JOB", &u->service_job,
+#endif // 0
"SLICE", &u->slice,
+/// elogind does not support slice jobs
+#if 0
"SLICE_JOB", &u->slice_job,
+#endif // 0
"DISPLAY", &display,
"REALTIME", &realtime,
"MONOTONIC", &monotonic,
@@ -325,10 +347,10 @@ static int user_mkdir_runtime_path(User *u) {
} else
p = u->runtime_path;
- if (path_is_mount_point(p, false) <= 0) {
+ if (path_is_mount_point(p, 0) <= 0) {
_cleanup_free_ char *t = NULL;
- (void) mkdir(p, 0700);
+ (void) mkdir_label(p, 0700);
if (mac_smack_use())
r = asprintf(&t, "mode=0700,smackfsroot=*,uid=" UID_FMT ",gid=" GID_FMT ",size=%zu", u->uid, u->gid, u->manager->runtime_dir_size);
@@ -356,6 +378,10 @@ static int user_mkdir_runtime_path(User *u) {
goto fail;
}
}
+
+ r = label_fix(p, false, false);
+ if (r < 0)
+ log_warning_errno(r, "Failed to fix label of '%s', ignoring: %m", p);
}
u->runtime_path = p;
@@ -373,7 +399,7 @@ fail:
}
static int user_start_slice(User *u) {
- char *job;
+ // char *job;
int r;
assert(u);
@@ -387,15 +413,21 @@ static int user_start_slice(User *u) {
if (r < 0)
return r;
+/// elogind : Do not try to use dbus to ask systemd
+#if 0
r = manager_start_unit(u->manager, slice, &error, &job);
+#endif // 0
if (r < 0) {
log_error("Failed to start user slice: %s", bus_error_message(&error, r));
free(slice);
} else {
u->slice = slice;
+/// elogind does not support slice jobs
+#if 0
free(u->slice_job);
u->slice_job = job;
+#endif // 0
}
}
@@ -407,7 +439,7 @@ static int user_start_slice(User *u) {
static int user_start_service(User *u) {
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
- char *job;
+ // char *job;
int r;
assert(u);
@@ -420,15 +452,21 @@ static int user_start_service(User *u) {
if (r < 0)
return log_error_errno(r, "Failed to build service name: %m");
+/// elogind : Do not try to use dbus to ask systemd
+#if 0
r = manager_start_unit(u->manager, service, &error, &job);
+#endif // 0
if (r < 0) {
log_error("Failed to start user service: %s", bus_error_message(&error, r));
free(service);
} else {
u->service = service;
+/// elogind does not support service jobs
+#if 0
free(u->service_job);
u->service_job = job;
+#endif // 0
}
}
@@ -458,6 +496,12 @@ int user_start(User *u) {
if (r < 0)
return r;
+ /* Save the user data so far, because pam_systemd will read the
+ * XDG_RUNTIME_DIR out of it while starting up systemd --user.
+ * We need to do user_save_internal() because we have not
+ * "officially" started yet. */
+ user_save_internal(u);
+
/* Spawn user systemd */
r = user_start_service(u);
if (r < 0)
@@ -476,10 +520,12 @@ int user_start(User *u) {
return 0;
}
+/// UNNEEDED by elogind
+#if 0
static int user_stop_slice(User *u) {
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
- char *job;
- int r;
+ // char *job;
+ int r = 0;
assert(u);
@@ -500,8 +546,8 @@ static int user_stop_slice(User *u) {
static int user_stop_service(User *u) {
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
- char *job;
- int r;
+ // char *job;
+ int r = 0;
assert(u);
@@ -519,6 +565,7 @@ static int user_stop_service(User *u) {
return r;
}
+#endif // 0
static int user_remove_runtime_path(User *u) {
int r;
@@ -567,6 +614,8 @@ int user_stop(User *u, bool force) {
}
/* Kill systemd */
+/// elogind does not support service or slice jobs
+#if 0
k = user_stop_service(u);
if (k < 0)
r = k;
@@ -575,6 +624,7 @@ int user_stop(User *u, bool force) {
k = user_stop_slice(u);
if (k < 0)
r = k;
+#endif // 0
u->stopping = true;
@@ -624,7 +674,7 @@ int user_finalize(User *u) {
int user_get_idle_hint(User *u, dual_timestamp *t) {
Session *s;
bool idle_hint = true;
- dual_timestamp ts = { 0, 0 };
+ dual_timestamp ts = DUAL_TIMESTAMP_NULL;
assert(u);
@@ -682,11 +732,14 @@ bool user_check_gc(User *u, bool drop_not_started) {
if (user_check_linger_file(u) > 0)
return true;
+/// elogind does not support systemd services and slices
+#if 0
if (u->slice_job && manager_job_is_active(u->manager, u->slice_job))
return true;
if (u->service_job && manager_job_is_active(u->manager, u->service_job))
return true;
+#endif // 0
return false;
}
@@ -709,7 +762,12 @@ UserState user_get_state(User *u) {
if (u->stopping)
return USER_CLOSING;
- if (u->slice_job || u->service_job)
+/// elogind does not support slice and service jobs
+#if 0
+ if (!u->started || u->slice_job || u->service_job)
+#else
+ if (!u->started)
+#endif // 0
return USER_OPENING;
if (u->sessions) {
@@ -737,60 +795,84 @@ UserState user_get_state(User *u) {
int user_kill(User *u, int signo) {
assert(u);
+/// FIXME: Without direct cgroup support, elogind can not kill users
+#if 0
if (!u->slice)
return -ESRCH;
return manager_kill_unit(u->manager, u->slice, KILL_ALL, signo, NULL);
+#else
+ return -ESRCH;
+#endif // 0
+}
+
+static bool elect_display_filter(Session *s) {
+ /* Return true if the session is a candidate for the user’s ‘primary
+ * session’ or ‘display’. */
+ assert(s);
+
+ return (s->class == SESSION_USER && !s->stopping);
+}
+
+static int elect_display_compare(Session *s1, Session *s2) {
+ /* Indexed by SessionType. Lower numbers mean more preferred. */
+ const int type_ranks[_SESSION_TYPE_MAX] = {
+ [SESSION_UNSPECIFIED] = 0,
+ [SESSION_TTY] = -2,
+ [SESSION_X11] = -3,
+ [SESSION_WAYLAND] = -3,
+ [SESSION_MIR] = -3,
+ [SESSION_WEB] = -1,
+ };
+
+ /* Calculate the partial order relationship between s1 and s2,
+ * returning < 0 if s1 is preferred as the user’s ‘primary session’,
+ * 0 if s1 and s2 are equally preferred or incomparable, or > 0 if s2
+ * is preferred.
+ *
+ * s1 or s2 may be NULL. */
+ if (!s1 && !s2)
+ return 0;
+
+ if ((s1 == NULL) != (s2 == NULL))
+ return (s1 == NULL) - (s2 == NULL);
+
+ if (s1->stopping != s2->stopping)
+ return s1->stopping - s2->stopping;
+
+ if ((s1->class != SESSION_USER) != (s2->class != SESSION_USER))
+ return (s1->class != SESSION_USER) - (s2->class != SESSION_USER);
+
+ if ((s1->type == _SESSION_TYPE_INVALID) != (s2->type == _SESSION_TYPE_INVALID))
+ return (s1->type == _SESSION_TYPE_INVALID) - (s2->type == _SESSION_TYPE_INVALID);
+
+ if (s1->type != s2->type)
+ return type_ranks[s1->type] - type_ranks[s2->type];
+
+ return 0;
}
void user_elect_display(User *u) {
- Session *graphical = NULL, *text = NULL, *other = NULL, *s;
+ Session *s;
assert(u);
/* This elects a primary session for each user, which we call
* the "display". We try to keep the assignment stable, but we
* "upgrade" to better choices. */
+ log_debug("Electing new display for user %s", u->name);
LIST_FOREACH(sessions_by_user, s, u->sessions) {
-
- if (s->class != SESSION_USER)
+ if (!elect_display_filter(s)) {
+ log_debug("Ignoring session %s", s->id);
continue;
+ }
- if (s->stopping)
- continue;
-
- if (SESSION_TYPE_IS_GRAPHICAL(s->type))
- graphical = s;
- else if (s->type == SESSION_TTY)
- text = s;
- else
- other = s;
- }
-
- if (graphical &&
- (!u->display ||
- u->display->class != SESSION_USER ||
- u->display->stopping ||
- !SESSION_TYPE_IS_GRAPHICAL(u->display->type))) {
- u->display = graphical;
- return;
- }
-
- if (text &&
- (!u->display ||
- u->display->class != SESSION_USER ||
- u->display->stopping ||
- u->display->type != SESSION_TTY)) {
- u->display = text;
- return;
+ if (elect_display_compare(s, u->display) < 0) {
+ log_debug("Choosing session %s in preference to %s", s->id, u->display ? u->display->id : "-");
+ u->display = s;
+ }
}
-
- if (other &&
- (!u->display ||
- u->display->class != SESSION_USER ||
- u->display->stopping))
- u->display = other;
}
static const char* const user_state_table[_USER_STATE_MAX] = {
diff --git a/src/login/logind-user.h b/src/login/logind-user.h
index 722247806..b30e7d60c 100644
--- a/src/login/logind-user.h
+++ b/src/login/logind-user.h
@@ -47,11 +47,17 @@ struct User {
char *state_file;
char *runtime_path;
+ /* These are always NULL, and here just for logind-user-dbus.c
+ to easily provide a NULL value for the user's service and
+ slice properties. */
char *service;
char *slice;
+/// UNNEEDED (and unsupported) by elogind
+#if 0
char *service_job;
char *slice_job;
+#endif // 0
Session *display;
diff --git a/src/login/logind.h b/src/login/logind.h
index c0ae52359..a74a3e483 100644
--- a/src/login/logind.h
+++ b/src/login/logind.h
@@ -185,13 +185,13 @@ int bus_manager_shutdown_or_sleep_now_or_later(Manager *m, const char *unit_name
int manager_send_changed(Manager *manager, const char *property, ...) _sentinel_;
-int manager_start_scope(Manager *manager, const char *scope, pid_t pid, const char *slice, const char *description, const char *after, const char *after2, sd_bus_error *error, char **job);
-int manager_start_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job);
-int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job);
-int manager_abandon_scope(Manager *manager, const char *scope, sd_bus_error *error);
-int manager_kill_unit(Manager *manager, const char *unit, KillWho who, int signo, sd_bus_error *error);
-int manager_unit_is_active(Manager *manager, const char *unit);
-int manager_job_is_active(Manager *manager, const char *path);
+// UNNEEDED int manager_start_scope(Manager *manager, const char *scope, pid_t pid, const char *slice, const char *description, const char *after, const char *after2, sd_bus_error *error, char **job);
+// UNNEEDED int manager_start_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job);
+// UNNEEDED int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job);
+// UNNEEDED int manager_abandon_scope(Manager *manager, const char *scope, sd_bus_error *error);
+// UNNEEDED int manager_kill_unit(Manager *manager, const char *unit, KillWho who, int signo, sd_bus_error *error);
+// UNNEEDED int manager_unit_is_active(Manager *manager, const char *unit);
+// UNNEEDED int manager_job_is_active(Manager *manager, const char *path);
/* gperf lookup function */
const struct ConfigPerfItem* logind_gperf_lookup(const char *key, GPERF_LEN_TYPE length);