[personal profile] mjg59
A reasonably common design for applications that want to run code at a specific time is something like:

time_t wakeup_time = get_next_event_time();
time_t now = time(NULL);
sleep(wakeup_time-now);

This works absolutely fine, except that sleep() ignores time spent with a suspended system. If you sleep(3600) and then immediately suspend for 45 minutes you'll wake up after 105 minutes, not 60. Which probably isn't what you want. If you want a timer that'll expire at a specific time (or immediately after resume if that time passed during suspend), use the POSIX timer family (timer_create, timer_settime and friends) with CLOCK_REALTIME. It's a signal-driven interface rather than a blocking one, so implementation may be a little more complicated, but it has the advantage of actually working.

Date: 2011-11-17 02:17 pm (UTC)
From: (Anonymous)
Just out of interest: Why did nobody fix sleep() instead?

Different purposes ?

Date: 2011-11-17 02:36 pm (UTC)
From: (Anonymous)
… because they serve different purposes ?

Date: 2011-11-17 06:40 pm (UTC)
From: (Anonymous)
What is the argument that "realtime" should not just be the intuitive "real wall-clock time that normal people normally care about"?

Date: 2011-11-18 04:19 am (UTC)
From: (Anonymous)

I would think that 'realtime' in the spec says real time, not computer experienced time.

Date: 2011-11-17 10:02 pm (UTC)
From: (Anonymous)
The reason why I asked is that we have a similar issue in glib with g_timeout_add(). And I've been wondering if the correct approach is to do what you did and then adding a g_call_me_when_this_clock_time_has_been_hit() callback for being woken up at a certain point in time. Or if it's better to do it the other way.

What do most people actually expect when they schedule a timeout or call sleep()? Any guesses?

Date: 2011-11-19 02:21 am (UTC)
From: (Anonymous)
With the line between a system being awake and a system being asleep getting blurrier and blurrier, it seems a very good idea to fix this behaviour before it is going to bite everyone when things like autosuspend become more common.

I am not claiming that the current behaviour is against the spec, but come on, let common sense kick in and fix this madness.

Using something else than sleep() is not an option because select/poll/etc. have the same unexpected behaviour.

Date: 2011-11-20 12:28 am (UTC)
From: (Anonymous)
Some people may expect sleep() to mean "I have 10 minutes of computation to do in another thread, so don't wake me up until that computation is over."

(However wrong sleep() is for the formulation that I have written here, that's just because I can't clean up the formulation to make sleep() sensible.)

Now he tells me.

Date: 2011-11-17 02:43 pm (UTC)
From: (Anonymous)
Couldn't you have written that yesterday? Would have saved me many minutes of worry.

:-)


timerfd

Date: 2011-11-17 03:09 pm (UTC)
From: (Anonymous)
If you don't like the signal-driven interface and are not married to POSIX you can use a timerfd which gives you a blocking interface.

Date: 2011-11-17 03:57 pm (UTC)
heliumbreath: (Default)
From: [personal profile] heliumbreath
Changes in system time were traditionally another thing that caused issues, though that was most infamously linked to X inactivity timeout triggering screenlock, which wouldn't have been sleep(). It might have been nice to have had a SIGTIMEWHOOPS that gets sent on return-from-suspend, clock changes, and other real-world botherations of the normal happy computer model.

Another thought is that one could explore changing the sleep() model in the kernel; good userspace code should handle an early return, so coming back per the other interpretation might cause less trouble.

Date: 2011-11-17 04:00 pm (UTC)
From: (Anonymous)
What about select() and poll() - do they have the same problem as sleep()?

Date: 2011-11-17 04:34 pm (UTC)
From: [identity profile] mas90.livejournal.com
The load spike when I wake up from suspend is already bad enough -- will this not just make it worse? Applying a bit of jitter to timeouts, as sleep() does in this case, can be a good thing...

Date: 2011-11-17 04:40 pm (UTC)
From: (Anonymous)
I have a program that presently uses select() to put the thread to sleep until a designated wake-up time. However, if the computer running the program is suspended at the moment select() is supposed to time out at, when the computer resumes, select() is still waiting and does not time out until the next signal interrupts it. Therefore yes - it would appear that select() suffers from this as well.

I like the idea of a signal that gets raised whenever the computer resumes so that these mechanisms can be notified that they may need to re-evaluate the passage of time.

Date: 2011-11-18 11:16 pm (UTC)
ewx: (Default)
From: [personal profile] ewx
That seems rather perverse (as an interpretation of the timeout to select).

Date: 2011-11-18 12:37 am (UTC)
From: (Anonymous)
Also checkout the recent CLOCK_REALTIME_ALARM and CLOCK_BOOTTIME_ALARM clockids, which allow normal posix timers to be set which will rouse the system out of suspend (if needed) in order to fire the timers.

Date: 2011-11-18 12:41 am (UTC)
From: (Anonymous)
Also clock_nanosleep() allows similar usage with any of the system clockids

Profile

Matthew Garrett

About Matthew

Power management, mobile and firmware developer on Linux. Security developer at Aurora. Ex-biologist. [personal profile] mjg59 on Twitter. Content here should not be interpreted as the opinion of my employer. Also on Mastodon.

Page Summary

Expand Cut Tags

No cut tags