From: Lennart Poettering Date: Thu, 4 Apr 2013 16:31:22 +0000 (+0200) Subject: login: add sd_login_monitor_get_timeout() public api call X-Git-Tag: v201~64 X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=commitdiff_plain;h=667c24a6a86a5a26a906b7477ae81dcf4c73e64e login: add sd_login_monitor_get_timeout() public api call We don't need this right now, but we should keep our options open, in case we need more than just an fd for waking up. --- diff --git a/man/sd_login_monitor_new.xml b/man/sd_login_monitor_new.xml index 94428771a..b187ad0db 100644 --- a/man/sd_login_monitor_new.xml +++ b/man/sd_login_monitor_new.xml @@ -48,6 +48,7 @@ sd_login_monitor_flush sd_login_monitor_get_fd sd_login_monitor_get_events + sd_login_monitor_get_timeout sd_login_monitor Monitor login sessions, seats and users @@ -82,6 +83,12 @@ sd_login_monitor* m + + int sd_login_monitor_get_timeout + sd_login_monitor* m + uint64_t* timeout_usec + + @@ -130,7 +137,9 @@ or a similar interface. The application should include the returned file descriptor as wake-up source for the events mask returned by - sd_login_monitor_get_events(). Whenever + sd_login_monitor_get_events(). It + should pass a timeout value as returned by + sd_login_monitor_get_timeout(). Whenever a wake-up is triggered the file descriptor needs to be reset via sd_login_monitor_flush(). An @@ -146,15 +155,51 @@ and similar to fill into the .events field of struct pollfd. + + sd_login_monitor_get_timeout() + will return a timeout value for usage in + poll(). This returns a value in + microseconds since the epoch of CLOCK_MONOTONIC for + timing out poll() in + timeout_usec. See + clock_gettime2 + for details about + CLOCK_MONOTONIC. If there's no + timeout to wait for this will fill in + (uint64_t) -1 instead. Note that + poll() takes a relative timeout + in milliseconds rather than an absolute timeout in + microseconds. To convert the absolute 'us' timeout into + relative 'ms', use code like the following: + + uint64_t t; +int msec; +sd_login_monitor_get_timeout(m, &t); +if (t == (uint64_t) -1) + msec = -1; +else { + struct timespec ts; + uint64_t n; + clock_getttime(CLOCK_MONOTONIC, &ts); + n = (uint64_t) ts.tv_sec * 1000000 + ts.tv_nsec / 1000; + msec = t > n ? (int) ((t - n + 999) / 1000) : 0; +} + + The code above does not do any error checking + for brevity's sake. The calculated msec + integer can be passed directly as + poll()'s timeout + parameter. Return Value On success - sd_login_monitor_new() and - sd_login_monitor_flush() return 0 - or a positive integer. On success + sd_login_monitor_new(), + sd_login_monitor_flush() and + sd_login_monitor_get_timeout() + return 0 or a positive integer. On success sd_login_monitor_get_fd() returns a Unix file descriptor. On success sd_login_monitor_get_events() @@ -173,8 +218,9 @@ The sd_login_monitor_new(), sd_login_monitor_unref(), sd_login_monitor_flush(), - sd_login_monitor_get_fd() and - sd_login_monitor_get_events() + sd_login_monitor_get_fd(), + sd_login_monitor_get_events() and + sd_login_monitor_get_timeout() interfaces are available as shared library, which can be compiled and linked to with the libsystemd-login @@ -189,7 +235,8 @@ systemd1, sd-login3, sd_get_seats3, - poll2 + poll2, + clock_gettime2 diff --git a/src/login/libsystemd-login.sym b/src/login/libsystemd-login.sym index 55a828773..ce2304a1b 100644 --- a/src/login/libsystemd-login.sym +++ b/src/login/libsystemd-login.sym @@ -62,4 +62,5 @@ global: LIBSYSTEMD_LOGIN_201 { global: sd_login_monitor_get_events; + sd_login_monitor_get_timeout; } LIBSYSTEMD_LOGIN_198; diff --git a/src/login/sd-login.c b/src/login/sd-login.c index 861a57166..7513f76cb 100644 --- a/src/login/sd-login.c +++ b/src/login/sd-login.c @@ -804,5 +804,23 @@ _public_ int sd_login_monitor_get_events(sd_login_monitor *m) { if (!m) return -EINVAL; + /* For now we will only return POLLIN here, since we don't + * need anything else ever for inotify. However, let's have + * this API to keep our options open should we later on need + * it. */ return POLLIN; } + +_public_ int sd_login_monitor_get_timeout(sd_login_monitor *m, uint64_t *timeout_usec) { + + if (!m) + return -EINVAL; + if (!timeout_usec) + return -EINVAL; + + /* For now we will only return (uint64_t) -1, since we don't + * need any timeout. However, let's have this API to keep our + * options open should we later on need it. */ + *timeout_usec = (uint64_t) -1; + return 0; +} diff --git a/src/login/test-login.c b/src/login/test-login.c index f63912963..e4d0c9337 100644 --- a/src/login/test-login.c +++ b/src/login/test-login.c @@ -183,12 +183,23 @@ int main(int argc, char* argv[]) { r = sd_login_monitor_new("session", &m); assert_se(r >= 0); - zero(pollfd); - pollfd.fd = sd_login_monitor_get_fd(m); - pollfd.events = sd_login_monitor_get_events(m); for (n = 0; n < 5; n++) { - r = poll(&pollfd, 1, -1); + usec_t timeout, nw; + + zero(pollfd); + assert_se((pollfd.fd = sd_login_monitor_get_fd(m)) >= 0); + assert_se((pollfd.events = sd_login_monitor_get_events(m)) >= 0); + + assert_se(sd_login_monitor_get_timeout(m, &timeout) >= 0); + + nw = now(CLOCK_MONOTONIC); + + r = poll(&pollfd, 1, + timeout == (uint64_t) -1 ? -1 : + timeout > nw ? (int) ((timeout - nw) / 1000) : + 0); + assert_se(r >= 0); sd_login_monitor_flush(m); diff --git a/src/systemd/sd-login.h b/src/systemd/sd-login.h index 57255bd4a..d05424dbf 100644 --- a/src/systemd/sd-login.h +++ b/src/systemd/sd-login.h @@ -23,6 +23,7 @@ ***/ #include +#include #ifdef __cplusplus extern "C" { @@ -159,6 +160,9 @@ int sd_login_monitor_get_fd(sd_login_monitor *m); /* Get poll() mask to monitor */ int sd_login_monitor_get_events(sd_login_monitor *m); +/* Get timeout for poll(), as usec value relative to CLOCK_MONOTONIC's epoch */ +int sd_login_monitor_get_timeout(sd_login_monitor *m, uint64_t *timeout_usec); + #ifdef __cplusplus } #endif