From eecd1362f7f4de432483b5d77c56726c3621a83a Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 5 May 2012 00:34:48 +0200 Subject: logind: implement delay inhibitor locks in addition to block inhibitor locks This is useful to allow applications to synchronously save data before the system is suspended or shut down. --- src/login/logind.c | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) (limited to 'src/login/logind.c') diff --git a/src/login/logind.c b/src/login/logind.c index 6b7012ec73..5860bfc8d7 100644 --- a/src/login/logind.c +++ b/src/login/logind.c @@ -50,6 +50,7 @@ Manager *manager_new(void) { m->udev_vcsa_fd = -1; m->epoll_fd = -1; m->n_autovts = 6; + m->inhibit_delay_max = 5 * USEC_PER_SEC; m->devices = hashmap_new(string_hash_func, string_compare_func); m->seats = hashmap_new(string_hash_func, string_compare_func); @@ -1163,7 +1164,7 @@ int manager_get_idle_hint(Manager *m, dual_timestamp *t) { assert(m); - idle_hint = !manager_is_inhibited(m, INHIBIT_IDLE, t); + idle_hint = !manager_is_inhibited(m, INHIBIT_IDLE, INHIBIT_BLOCK, t); HASHMAP_FOREACH(s, m->sessions, i) { dual_timestamp k; @@ -1264,15 +1265,28 @@ int manager_run(Manager *m) { for (;;) { struct epoll_event event; int n; + int msec = -1; manager_gc(m, true); + if (manager_dispatch_delayed_shutdown(m) > 0) + continue; + if (dbus_connection_dispatch(m->bus) != DBUS_DISPATCH_COMPLETE) continue; manager_gc(m, true); - n = epoll_wait(m->epoll_fd, &event, 1, -1); + if (m->delayed_shutdown) { + usec_t x, y; + + x = now(CLOCK_MONOTONIC); + y = m->delayed_shutdown_timestamp + m->inhibit_delay_max; + + msec = x >= y ? 0 : (int) ((y - x) / USEC_PER_MSEC); + } + + n = epoll_wait(m->epoll_fd, &event, 1, msec); if (n < 0) { if (errno == EINTR || errno == EAGAIN) continue; @@ -1281,6 +1295,9 @@ int manager_run(Manager *m) { return -errno; } + if (n == 0) + continue; + switch (event.data.u32) { case FD_SEAT_UDEV: -- cgit v1.2.3-54-g00ecf