Linux idle time detection broken

Moderators: Site Moderators, FAHC Science Team

Linux idle time detection broken

Postby MrBurritoTaco » Tue Apr 21, 2020 3:46 am

The idle detection algorithm seems to be broken in Linux, even though X Server provides this information in it's API see this
Code: Select all
https://github.com/gpolitis/xidle/blob/master/xidle.c or
https://github.com/g0hl1n/xprintidle/blob/master/xprintidle.c


xidle is show below
Code: Select all
#include <stdio.h>
#include <X11/extensions/scrnsaver.h>

main() {
  XScreenSaverInfo *info = XScreenSaverAllocInfo();
  Display *display = XOpenDisplay(0);

  XScreenSaverQueryInfo(display, DefaultRootWindow(display), info);
  printf("%u ms\n", info->idle);
}

This code upon testing produces segfaults when the info or display pointers are NULL and is therefore unsafe for use, it however does show what is needed at a minimum to get idle time in milliseconds.
xprintidle is a safer approach as it contains error checking and a workarounds for some systems. (See workaroundCreepyXServer in xprintidle link).

This will only work on systems with an xserver running, which will still leave headless systems with broken idle time detection. You could use the 'w' command and awk something useful out of it, or possibly grab the source here
Code: Select all
https://gitlab.com/procps-ng/procps/-/blob/master/w.c
as a baseline to derive what's needed.
MrBurritoTaco
 
Posts: 2
Joined: Tue Apr 21, 2020 2:29 am

Re: Linux idle time detection broken

Postby MrBurritoTaco » Tue Apr 21, 2020 6:22 am

For those looking for a workaround, here's a simple python script I made. Ensure that While I'm Working is checked and that you have 'xprintidle' installed, on ubuntu sudo apt install xprintidle should do.

Code: Select all
#!/usr/bin/env python
from sys import argv
from time import sleep
from subprocess import Popen, PIPE

interval = 10 #Number of checks a minute
idle_minutes = 3 if len(argv) == 1 else float(argv[1]) #default to 3 min
paused = False #Assume running, will send a paused signal right away

while True:

  idle_time = int(Popen(["env", "DISPLAY=:0.0", "xprintidle"], stdout=PIPE).stdout.read())
  if idle_time > idle_minutes * 60000 and paused:
    Popen(["FAHClient", "--send-unpause"], stdout=PIPE)
    print "resume"
    paused = False
  if idle_time < idle_minutes * 60000 and not paused:
    Popen(["FAHClient", "--send-pause"], stdout=PIPE)
    print "pause"
    paused = True

  sleep(60 / interval)
MrBurritoTaco
 
Posts: 2
Joined: Tue Apr 21, 2020 2:29 am


Return to V7.5.1 Public Release Windows/Linux/MacOS X

Who is online

Users browsing this forum: No registered users and 0 guests

cron