Skip to content

Commit cde0ce5

Browse files
Merge pull request #6242 from BOINC/dpa_idle_time2
client (Unix): add support for idle detection in a separate process
2 parents 26fa474 + 34803eb commit cde0ce5

4 files changed

Lines changed: 104 additions & 12 deletions

File tree

client/Makefile.linux

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ LIBS = ../lib/boinc.a \
144144
-lpthread \
145145
-lX11 \
146146
-lcurl -lssl -lcrypto \
147-
-lz -ldl
147+
-lz -ldl -lrt
148148

149149
.cpp.o:
150150
$(CC) -c -o $*.o $<

client/hostinfo_unix.cpp

Lines changed: 97 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,9 @@
4949
#include <cstdlib>
5050
#include <cstring>
5151
#include <ctime>
52-
52+
#include <fcntl.h>
53+
#include <sys/mman.h>
54+
#include <sys/stat.h>
5355
#include <sys/param.h>
5456

5557
#if HAVE_SYS_TYPES_H
@@ -65,8 +67,6 @@
6567
#include <sys/vmmeter.h>
6668
#endif
6769

68-
#include <sys/stat.h>
69-
7070
#if HAVE_SYS_SWAP_H
7171
#include <sys/swap.h>
7272
#endif
@@ -106,6 +106,7 @@
106106
#include "error_numbers.h"
107107
#include "common_defs.h"
108108
#include "filesys.h"
109+
#include "shmem.h"
109110
#include "str_util.h"
110111
#include "str_replace.h"
111112
#include "util.h"
@@ -541,12 +542,11 @@ static void parse_cpuinfo_linux(HOST_INFO& host) {
541542

542543
#if defined(__aarch64__) || defined(__arm__)
543544
if (
544-
// Hardware is specifying the board this CPU is on, store it in product_name while we parse /proc/cpuinfo
545+
// Hardware is specifying the board this CPU is on,
546+
// store it in product_name while we parse /proc/cpuinfo
545547
strstr(buf, "Hardware\t: ")
546548
) {
547-
// this makes sure we only ever copy as much bytes as we can still store in host.product_name
548-
int t = sizeof(host.product_name) - strlen(host.product_name) - 2;
549-
strlcpy(buf2, strchr(buf, ':') + 2, ((t<sizeof(buf2))?t:sizeof(buf2)));
549+
strlcpy(buf2, strchr(buf, ':') + 2, sizeof(buf2));
550550
strip_whitespace(buf2);
551551
if (strlen(host.product_name)) {
552552
safe_strcat(host.product_name, " ");
@@ -2291,9 +2291,92 @@ long xss_idle() {
22912291

22922292
#endif // LINUX_LIKE_SYSTEM
22932293

2294+
#ifndef ANDROID // Android doesn't have shm_open()
2295+
// idle time detection.
2296+
// old approach: do it ourselves by looking at devices
2297+
// and trying to get info from X11
2298+
// (big mess, permissions problems, doesn't generally work)
2299+
// new approach: get last-input time from a separate daemon process,
2300+
// communicated via shmem
2301+
2302+
bool get_idle_time_from_daemon(long &idle_time) {
2303+
static int64_t* seg_ptr = NULL;
2304+
if (!seg_ptr) {
2305+
int fd = shm_open("/idle_detect_shmem", O_RDONLY, 0);
2306+
if (fd < 0) {
2307+
return false;
2308+
}
2309+
2310+
struct stat st;
2311+
if (fstat(fd, &st)) {
2312+
close(fd);
2313+
return false;
2314+
}
2315+
if (st.st_size < 2*sizeof(int64_t)) {
2316+
close(fd);
2317+
return false;
2318+
}
2319+
2320+
int64_t* mapped_ptr = (int64_t*)mmap(
2321+
NULL, 2*sizeof(int64_t), PROT_READ, MAP_SHARED, fd, 0
2322+
);
2323+
close(fd);
2324+
if (mapped_ptr == MAP_FAILED) {
2325+
return false;
2326+
}
2327+
2328+
seg_ptr = mapped_ptr;
2329+
}
2330+
if (!seg_ptr) return false;
2331+
2332+
// make sure the shmem is actually being updated
2333+
//
2334+
int64_t update_time = seg_ptr[0];
2335+
if (update_time > gstate.now+10) return false;
2336+
if (update_time < gstate.now-60) return false;
2337+
2338+
int64_t input_time = seg_ptr[1];
2339+
idle_time = gstate.now - input_time;
2340+
//printf("idle time: %ld\n", idle_time);
2341+
return true;
2342+
}
2343+
2344+
bool detect_wayland() {
2345+
const char* wayland_display = getenv("WAYLAND_DISPLAY");
2346+
if (wayland_display && strlen(wayland_display)) {
2347+
return true;
2348+
}
2349+
const char* xdg_session_type = getenv("XDG_SESSION_TYPE");
2350+
if (xdg_session_type && strcmp(xdg_session_type, "wayland") == 0) {
2351+
return true;
2352+
}
2353+
return false;
2354+
}
2355+
2356+
#endif // !ANDROID
2357+
2358+
// get idle time. Try the new approach, if it fails use old
2359+
//
22942360
long HOST_INFO::user_idle_time(bool check_all_logins) {
22952361
long idle_time = USER_IDLE_TIME_INF;
22962362

2363+
#ifndef ANDROID
2364+
static bool show_idle_time_legacy_warning = true;
2365+
if (get_idle_time_from_daemon(idle_time)) {
2366+
show_idle_time_legacy_warning = false;
2367+
return idle_time;
2368+
}
2369+
2370+
if (show_idle_time_legacy_warning) {
2371+
msg_printf(NULL, MSG_INFO,
2372+
"Currently BOINC uses legacy idle detection methods that might not \
2373+
work properly on all systems. Please consider installing a modern idle detection \
2374+
utility that works on Wayland and X11: \
2375+
https://github.com/jamescowens/idle_detect");
2376+
show_idle_time_legacy_warning = false;
2377+
}
2378+
#endif
2379+
22972380
#if HAVE_UTMP_H
22982381
if (check_all_logins) {
22992382
idle_time = min(idle_time, all_logins_idle());
@@ -2305,7 +2388,13 @@ long HOST_INFO::user_idle_time(bool check_all_logins) {
23052388
#if LINUX_LIKE_SYSTEM
23062389

23072390
#if HAVE_XSS
2308-
idle_time = min(idle_time, xss_idle());
2391+
#ifndef ANDROID
2392+
static bool wayland_detected = detect_wayland();
2393+
if (!wayland_detected) {
2394+
//printf("Using XScreenSaver API for idle detection\n");
2395+
idle_time = min(idle_time, xss_idle());
2396+
}
2397+
#endif // !ANDROID
23092398
#endif // HAVE_XSS
23102399

23112400
#else

configure.ac

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -556,7 +556,7 @@ dnl Special rules for specific targets go here: It's easier to add static libs
556556
dnl than subtract them. If you need to remove something from the list above,
557557
dnl please add it to the lists below...
558558
case ${target} in
559-
*-linux*|*-k*bsd*-gnu) STATIC_LIB_LIST="${STATIC_LIB_LIST} nsl"
559+
*-linux*|*-k*bsd*-gnu) STATIC_LIB_LIST="${STATIC_LIB_LIST} nsl rt"
560560
;;
561561
*-solaris*) STATIC_LIB_LIST="${STATIC_LIB_LIST} X* ssl crypto"
562562
;;
@@ -594,7 +594,7 @@ ERROR: could not find (recent enough) development-libs for libcurl.
594594
],
595595
[
596596
## add libcurl et al. to the list of statically linked libs
597-
STATIC_LIB_LIST="${STATIC_LIB_LIST} curl idn ssh2 crypto ssl krb5 k5crypto gssapi_krb5 com_err resolv lber ldap socket nsl z rt gcrypt gpg-error"
597+
STATIC_LIB_LIST="${STATIC_LIB_LIST} curl idn ssh2 ssl crypto krb5 k5crypto gssapi_krb5 com_err resolv lber ldap socket nsl z rt gcrypt gpg-error"
598598
CPPFLAGS="${CPPFLAGS} ${LIBCURL_CPPFLAGS}"
599599
CURL_LIB_PATHS=`echo $LIBCURL | sed 's/[^[a-zA-Z]]*-l[^ ]*//g'`
600600
@@ -628,6 +628,8 @@ SAH_CHECK_LIB([freetype], [fopen],
628628
[BOINC_EXTRA_LIBS="${BOINC_EXTRA_LIBS} ${sah_lib_last}"])
629629
SAH_CHECK_LIB([socket], [bind],
630630
[BOINC_EXTRA_LIBS="${BOINC_EXTRA_LIBS} ${sah_lib_last}"])
631+
SAH_CHECK_LIB([rt], [shm_open],
632+
[BOINC_EXTRA_LIBS="${BOINC_EXTRA_LIBS} ${sah_lib_last}"])
631633
SAH_CHECK_LIB([z], [gzopen], [
632634
zlib_found=yes
633635
BOINC_EXTRA_LIBS="${BOINC_EXTRA_LIBS} ${sah_lib_last}"])

lib/hostinfo.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,8 @@ class HOST_INFO {
126126

127127
bool host_is_running_on_batteries();
128128
long user_idle_time(bool check_all_logins);
129-
// seconds since last user interaction
129+
// seconds since last user interaction,
130+
// or a large number (USER_IDLE_TIME_INF) if we have no info
130131
int get_host_info(bool init);
131132
int get_cpu_info();
132133
int get_cpu_count();

0 commit comments

Comments
 (0)