mirror of
https://github.com/systemd/systemd.git
synced 2024-11-05 23:51:28 +03:00
logind: use pipe fd to detect when a session is dead
This commit is contained in:
parent
094062918c
commit
31b79c2b4a
@ -437,7 +437,9 @@ static int bus_manager_create_session(Manager *m, DBusMessage *message, DBusMess
|
||||
goto fail;
|
||||
}
|
||||
|
||||
session->pipe_fd = pipe_fds[0];
|
||||
r = session_set_pipe_fd(session, pipe_fds[0]);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
pipe_fds[0] = -1;
|
||||
|
||||
if (s) {
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/epoll.h>
|
||||
|
||||
#include "logind-session.h"
|
||||
#include "strv.h"
|
||||
@ -97,8 +98,7 @@ void session_free(Session *s) {
|
||||
|
||||
hashmap_remove(s->manager->sessions, s->id);
|
||||
|
||||
if (s->pipe_fd >= 0)
|
||||
close_nointr_nofail(s->pipe_fd);
|
||||
session_unset_pipe_fd(s);
|
||||
|
||||
free(s->state_file);
|
||||
free(s);
|
||||
@ -729,6 +729,45 @@ void session_set_idle_hint(Session *s, bool b) {
|
||||
"IdleSinceHintMonotonic\0");
|
||||
}
|
||||
|
||||
int session_set_pipe_fd(Session *s, int fd) {
|
||||
struct epoll_event ev;
|
||||
int r;
|
||||
|
||||
assert(s);
|
||||
assert(fd >= 0);
|
||||
assert(s->pipe_fd < 0);
|
||||
|
||||
r = hashmap_put(s->manager->pipe_fds, INT_TO_PTR(fd + 1), s);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
zero(ev);
|
||||
ev.events = 0;
|
||||
ev.data.u32 = FD_PIPE_BASE + fd;
|
||||
|
||||
if (epoll_ctl(s->manager->epoll_fd, EPOLL_CTL_ADD, fd, &ev) < 0) {
|
||||
assert_se(hashmap_remove(s->manager->pipe_fds, INT_TO_PTR(fd + 1)) == s);
|
||||
return -errno;
|
||||
}
|
||||
|
||||
s->pipe_fd = fd;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void session_unset_pipe_fd(Session *s) {
|
||||
assert(s);
|
||||
|
||||
if (s->pipe_fd < 0)
|
||||
return;
|
||||
|
||||
assert_se(hashmap_remove(s->manager->pipe_fds, INT_TO_PTR(s->pipe_fd + 1)) == s);
|
||||
|
||||
assert_se(epoll_ctl(s->manager->epoll_fd, EPOLL_CTL_DEL, s->pipe_fd, NULL) == 0);
|
||||
|
||||
close_nointr_nofail(s->pipe_fd);
|
||||
s->pipe_fd = -1;
|
||||
}
|
||||
|
||||
int session_check_gc(Session *s) {
|
||||
int r;
|
||||
|
||||
|
@ -91,6 +91,8 @@ int session_activate(Session *s);
|
||||
bool session_is_active(Session *s);
|
||||
int session_get_idle_hint(Session *s, dual_timestamp *t);
|
||||
void session_set_idle_hint(Session *s, bool b);
|
||||
int session_set_pipe_fd(Session *s, int fd);
|
||||
void session_unset_pipe_fd(Session *s);
|
||||
int session_start(Session *s);
|
||||
int session_stop(Session *s);
|
||||
int session_save(Session *s);
|
||||
|
25
src/logind.c
25
src/logind.c
@ -33,12 +33,6 @@
|
||||
#include "dbus-common.h"
|
||||
#include "dbus-loop.h"
|
||||
|
||||
enum {
|
||||
FD_UDEV,
|
||||
FD_CONSOLE,
|
||||
FD_BUS
|
||||
};
|
||||
|
||||
Manager *manager_new(void) {
|
||||
Manager *m;
|
||||
|
||||
@ -57,6 +51,7 @@ Manager *manager_new(void) {
|
||||
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);
|
||||
m->pipe_fds = hashmap_new(trivial_hash_func, trivial_compare_func);
|
||||
|
||||
if (!m->devices || !m->seats || !m->sessions || !m->users) {
|
||||
manager_free(m);
|
||||
@ -102,6 +97,7 @@ void manager_free(Manager *m) {
|
||||
hashmap_free(m->devices);
|
||||
hashmap_free(m->seats);
|
||||
hashmap_free(m->cgroups);
|
||||
hashmap_free(m->pipe_fds);
|
||||
|
||||
if (m->console_active_fd >= 0)
|
||||
close_nointr_nofail(m->console_active_fd);
|
||||
@ -714,6 +710,19 @@ void manager_cgroup_notify_empty(Manager *m, const char *cgroup) {
|
||||
free(p);
|
||||
}
|
||||
|
||||
static void manager_pipe_notify_eof(Manager *m, int fd) {
|
||||
Session *s;
|
||||
|
||||
assert_se(m);
|
||||
assert_se(fd >= 0);
|
||||
|
||||
assert_se(s = hashmap_get(m->pipe_fds, INT_TO_PTR(fd + 1)));
|
||||
assert(s->pipe_fd == fd);
|
||||
session_unset_pipe_fd(s);
|
||||
|
||||
session_add_to_gc_queue(s);
|
||||
}
|
||||
|
||||
static int manager_connect_bus(Manager *m) {
|
||||
DBusError error;
|
||||
int r;
|
||||
@ -1006,6 +1015,10 @@ int manager_run(Manager *m) {
|
||||
case FD_BUS:
|
||||
bus_loop_dispatch(m->bus_fd);
|
||||
break;
|
||||
|
||||
default:
|
||||
if (event.data.u32 >= FD_PIPE_BASE)
|
||||
manager_pipe_notify_eof(m, event.data.u32 - FD_PIPE_BASE);
|
||||
}
|
||||
}
|
||||
|
||||
|
11
src/logind.h
11
src/logind.h
@ -37,9 +37,8 @@
|
||||
* recreate VTs when disallocated
|
||||
* spawn user systemd
|
||||
* direct client API
|
||||
* subscribe to fd HUP
|
||||
* D-Bus method: AttachDevice(seat, device);
|
||||
* D-Bus method: PermitLinger(user, bool b);
|
||||
* D-Bus method: SetLinger(user, bool b);
|
||||
*
|
||||
* non-local X11 server
|
||||
* reboot/shutdown halt management
|
||||
@ -86,6 +85,14 @@ struct Manager {
|
||||
unsigned long session_counter;
|
||||
|
||||
Hashmap *cgroups;
|
||||
Hashmap *pipe_fds;
|
||||
};
|
||||
|
||||
enum {
|
||||
FD_UDEV,
|
||||
FD_CONSOLE,
|
||||
FD_BUS,
|
||||
FD_PIPE_BASE
|
||||
};
|
||||
|
||||
Manager *manager_new(void);
|
||||
|
Loading…
Reference in New Issue
Block a user