mirror of
https://github.com/systemd/systemd.git
synced 2025-01-13 17:18:18 +03:00
logind: remove a session when its cgroup is gone
This commit is contained in:
parent
dec15e9263
commit
1713813de3
@ -896,6 +896,36 @@ const DBusObjectPathVTable bus_manager_vtable = {
|
||||
.message_function = manager_message_handler
|
||||
};
|
||||
|
||||
DBusHandlerResult bus_message_filter(
|
||||
DBusConnection *connection,
|
||||
DBusMessage *message,
|
||||
void *userdata) {
|
||||
|
||||
Manager *m = userdata;
|
||||
DBusError error;
|
||||
|
||||
assert(m);
|
||||
assert(connection);
|
||||
assert(message);
|
||||
|
||||
dbus_error_init(&error);
|
||||
|
||||
if (dbus_message_is_signal(message, "org.freedesktop.systemd1.Agent", "Released")) {
|
||||
const char *cgroup;
|
||||
|
||||
if (!dbus_message_get_args(message, &error,
|
||||
DBUS_TYPE_STRING, &cgroup,
|
||||
DBUS_TYPE_INVALID))
|
||||
log_error("Failed to parse Released message: %s", bus_error_message(&error));
|
||||
else
|
||||
manager_cgroup_notify_empty(m, cgroup);
|
||||
}
|
||||
|
||||
dbus_error_free(&error);
|
||||
|
||||
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
|
||||
}
|
||||
|
||||
int manager_send_changed(Manager *manager, const char *properties) {
|
||||
DBusMessage *m;
|
||||
int r = -ENOMEM;
|
||||
|
@ -83,6 +83,9 @@ void session_free(Session *s) {
|
||||
LIST_REMOVE(Session, sessions_by_seat, s->seat->sessions, s);
|
||||
}
|
||||
|
||||
if (s->cgroup_path)
|
||||
hashmap_remove(s->manager->cgroups, s->cgroup_path);
|
||||
|
||||
free(s->cgroup_path);
|
||||
strv_free(s->controllers);
|
||||
|
||||
@ -468,6 +471,8 @@ static int session_create_cgroup(Session *s) {
|
||||
}
|
||||
}
|
||||
|
||||
hashmap_put(s->manager->cgroups, s->cgroup_path, s);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -562,6 +567,8 @@ static int session_kill_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);
|
||||
|
||||
free(s->cgroup_path);
|
||||
s->cgroup_path = NULL;
|
||||
|
||||
|
38
src/logind.c
38
src/logind.c
@ -56,6 +56,7 @@ Manager *manager_new(void) {
|
||||
m->seats = hashmap_new(string_hash_func, string_compare_func);
|
||||
m->sessions = hashmap_new(string_hash_func, string_compare_func);
|
||||
m->users = hashmap_new(trivial_hash_func, trivial_compare_func);
|
||||
m->cgroups = hashmap_new(string_hash_func, string_compare_func);
|
||||
|
||||
if (!m->devices || !m->seats || !m->sessions || !m->users) {
|
||||
manager_free(m);
|
||||
@ -100,6 +101,7 @@ void manager_free(Manager *m) {
|
||||
hashmap_free(m->users);
|
||||
hashmap_free(m->devices);
|
||||
hashmap_free(m->seats);
|
||||
hashmap_free(m->cgroups);
|
||||
|
||||
if (m->console_active_fd >= 0)
|
||||
close_nointr_nofail(m->console_active_fd);
|
||||
@ -682,12 +684,34 @@ int manager_spawn_autovt(Manager *m, int vtnr) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static DBusHandlerResult login_message_filter(
|
||||
DBusConnection *connection,
|
||||
DBusMessage *message,
|
||||
void *userdata) {
|
||||
void manager_cgroup_notify_empty(Manager *m, const char *cgroup) {
|
||||
Session *s;
|
||||
char *p;
|
||||
|
||||
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
|
||||
assert(m);
|
||||
assert(cgroup);
|
||||
|
||||
p = strdup(cgroup);
|
||||
if (!p) {
|
||||
log_error("Out of memory.");
|
||||
return;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
char *e;
|
||||
|
||||
if (isempty(p) || streq(p, "/"))
|
||||
break;
|
||||
|
||||
s = hashmap_get(m->cgroups, p);
|
||||
if (s)
|
||||
session_add_to_gc_queue(s);
|
||||
|
||||
assert_se(e = strrchr(p, '/'));
|
||||
*e = 0;
|
||||
}
|
||||
|
||||
free(p);
|
||||
}
|
||||
|
||||
static int manager_connect_bus(Manager *m) {
|
||||
@ -712,7 +736,7 @@ static int manager_connect_bus(Manager *m) {
|
||||
!dbus_connection_register_fallback(m->bus, "/org/freedesktop/login1/seat", &bus_seat_vtable, m) ||
|
||||
!dbus_connection_register_fallback(m->bus, "/org/freedesktop/login1/session", &bus_session_vtable, m) ||
|
||||
!dbus_connection_register_fallback(m->bus, "/org/freedesktop/login1/user", &bus_user_vtable, m) ||
|
||||
!dbus_connection_add_filter(m->bus, login_message_filter, m, NULL)) {
|
||||
!dbus_connection_add_filter(m->bus, bus_message_filter, m, NULL)) {
|
||||
log_error("Not enough memory");
|
||||
r = -ENOMEM;
|
||||
goto fail;
|
||||
@ -958,6 +982,8 @@ int manager_run(Manager *m) {
|
||||
if (dbus_connection_dispatch(m->bus) != DBUS_DISPATCH_COMPLETE)
|
||||
continue;
|
||||
|
||||
manager_gc(m);
|
||||
|
||||
n = epoll_wait(m->epoll_fd, &event, 1, -1);
|
||||
if (n < 0) {
|
||||
if (errno == EINTR || errno == EAGAIN)
|
||||
|
@ -37,7 +37,7 @@
|
||||
* recreate VTs when disallocated
|
||||
* spawn user systemd
|
||||
* direct client API
|
||||
* subscribe to cgroup changes, fd HUP
|
||||
* subscribe to fd HUP
|
||||
* D-Bus method: AttachDevice(seat, device);
|
||||
* D-Bus method: PermitLinger(user, bool b);
|
||||
*
|
||||
@ -84,6 +84,8 @@ struct Manager {
|
||||
bool kill_user_processes;
|
||||
|
||||
unsigned long session_counter;
|
||||
|
||||
Hashmap *cgroups;
|
||||
};
|
||||
|
||||
Manager *manager_new(void);
|
||||
@ -109,6 +111,8 @@ int manager_startup(Manager *m);
|
||||
int manager_run(Manager *m);
|
||||
int manager_spawn_autovt(Manager *m, int vtnr);
|
||||
|
||||
void manager_cgroup_notify_empty(Manager *m, const char *cgroup);
|
||||
|
||||
void manager_gc(Manager *m);
|
||||
|
||||
int manager_get_idle_hint(Manager *m, dual_timestamp *t);
|
||||
@ -117,6 +121,8 @@ bool x11_display_is_local(const char *display);
|
||||
|
||||
extern const DBusObjectPathVTable bus_manager_vtable;
|
||||
|
||||
DBusHandlerResult bus_message_filter(DBusConnection *c, DBusMessage *message, void *userdata);
|
||||
|
||||
int manager_send_changed(Manager *manager, const char *properties);
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user