I've written a utility to talk to TomTom GPS watches over Bluetooth, and am trying to make it run nicely as a run-and-forget background daemon.
The program periodically communicates with the GPS device and then sleep
s for a while until it's needed again.
I've noticed that sleep()
interacts strangely with system suspend: when I enter system suspend (laptop running Linux 3.16.0 kernel) and then wake the computer back up, sleep
doesn't appear to notice the suspend time. For example, take the following sleep.c
:
#include <time.h>
#include <stdio.h>
#include <unistd.h>
int main(int argc, char**argv)
{
time_t t=time(NULL);
printf("sleep at: %s", ctime(&t));
sleep(atoi(argv[1]));
t=time(NULL);
printf("wake at: %s", ctime(&t));
}
dlenski@dlenski-ultra:~$
Compile, run, and sleep halfway through;
$ gcc sleep.c -o sleep
$ ./sleep 30
sleep at: Fri Aug 21 21:05:36 2015
<suspend computer for 17 seconds>
wake at: Fri Aug 21 21:06:23 2015
Is there a correct way to suspend program execution in a way that's clock-time-aware rather than system-uptime-aware?
(I've also tried usleep
, nanosleep
, and alarm
and found that they behave similarly.)
UPDATE: setitimer
, as suggested by @HuStmpHrrr, sounded quite promising... but appears to have the same problem.
This version pauses for more than the requested 30s when I suspend in the middle of it...
#include <time.h>
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <sys/time.h>
void sighandler() {}
int main(int argc, char**argv)
{
time_t t=time(NULL);
printf("sleep at: %s", ctime(&t));
signal(SIGALRM, sighandler);
struct itimerval timer = {.it_interval={0,0},
.it_value={atoi(argv[1]),0}};
setitimer(ITIMER_REAL, &timer, NULL);
pause();
t=time(NULL);
printf("wake at: %s", ctime(&t));
}
alarm
?alarm() arranges for a SIGALRM signal to be delivered to the calling process in seconds seconds.
reads promising. – Bitartratesetitimer
provides more control. you can pass inITIMER_REAL
to achieve what you want. – Bitartratesetitimer
looked very promising but appears to have the same issue in that it doesn't count "downtime." Pollingtime
seems like quite an inelegant solution but possibly the right one :( – Bibliophagepselect
. You can set a timeout for periodic returns, wait on 'interesting' events like file (descriptor) activity, as well as signal events. Even if you don't think you need all these features now - you get a much more flexible solution - and your utility looks like something interesting enough that you'll want more features and better response time in the future. – Bullardmin((real_time-real_start_time), 30s)
seems like a reasonable solution. – Bibliophagetimer_create(CLOCK_MONOTONIC,..)
, and set the next expiry in absolute time usingtimer_settime(...,TIMER_ABSTIME,...)
? (Or evenCLOCK_REALTIME
, really.) Such a timer should expire immediately after wake-up if the timer expired during suspend. These are all POSIX.1 too, so no Linux-specific/desktop environment shenanigans needed, either. – BreenCLOCK_REALTIME
andTIMER_ABSTIME
, per the docs: "If the value of the CLOCK_REALTIME clock is adjusted while an absolute timer based on that clock is armed, then the expiration of the timer will be appropriately adjusted. Adjustments to the CLOCK_REALTIME clock have no effect on relative timers based on that clock." If you want to write an answer, I'll gladly accept it, otherwise I'll add your solution to my answer. – BibliophageCLOCK_MONOTONIC
isn't adjusted, ever, and its zero epoch is arbitrary, otherwise it's similar toCLOCK_REALTIME
; that's why the passage you quoted does not apply to it. Because it's never adjusted. However, I haven't verified thatCLOCK_MONOTONIC
progresses during suspend, and that both kinds of timers get triggered immediately after resume, so that's why I used conditionals in my comment. You verified it, you answered it. :) – BreenCLOCK_MONOTONIC
appears to behave similarly toCLOCK_REALTIME
with system suspend. Since it doesn't actually simplify the code, and the documentation isn't clear that this behavior is guaranteed, I'll stick withCLOCK_REALTIME
for now. – Bibliophage