tag 624506 + patch
thanks

Matthew Garrett provided the attached patch.

Ansgar

--- Begin Message ---
at currently sleeps until the next job run. That's fine in most 
circumstances, but interacts badly with system suspend. When the machine 
resumes the sleep will continue as if the intervening time hadn't 
passed, delaying the next scheduled run. POSIX timers don't have this 
behaviour - they allow an absolute time to be provided (which avoids the 
delay) and will fire immediately if they expired while the system was 
suspended. This patch adds support for using them, while continuing to 
use time() and sleep() on systems that don't provide these functions.

diff -ur at-3.1.13/atd.c at-3.1.13.timer/atd.c
--- at-3.1.13/atd.c     2011-06-25 08:43:14.000000000 -0400
+++ at-3.1.13.timer/atd.c       2011-11-16 17:26:02.405420951 -0500
@@ -686,6 +686,54 @@
     return next_job;
 }
 
+#ifdef HAVE_CLOCK_GETTIME
+timer_t timer;
+struct itimerspec timeout;
+
+void timer_setup()
+{
+    struct sigevent sev;
+
+    sev.sigev_notify = SIGEV_SIGNAL;
+    sev.sigev_signo = SIGHUP;
+    sev.sigev_value.sival_ptr = &timer;
+
+    memset(&timeout, 0, sizeof(timeout));
+
+    if (timer_create(CLOCK_REALTIME, &sev, &timer) < 0)
+           pabort("unable to create timer");
+}
+
+time_t atd_gettime()
+{
+    struct timespec curtime;
+
+    clock_gettime(CLOCK_REALTIME, &curtime);
+
+    return curtime.tv_sec;
+}
+
+void atd_setalarm(time_t next)
+{
+    timeout.it_value.tv_sec = next;
+    timer_settime(timer, TIMER_ABSTIME, &timeout, NULL);
+    pause();
+}
+#else
+void timer_setup()
+{
+}
+
+time_t atd_gettime()
+{
+    return time(NULL);
+}
+
+void atd_setalarm(time_t next)
+{
+    sleep(next - atd_gettime());
+}
+#endif
 /* Global functions */
 
 int
@@ -783,7 +831,7 @@
     sigaction(SIGCHLD, &act, NULL);
 
     if (!run_as_daemon) {
-       now = time(NULL);
+       now = atd_gettime();
        run_loop();
        exit(EXIT_SUCCESS);
     }
@@ -806,13 +854,15 @@
     act.sa_handler = set_term;
     sigaction(SIGINT, &act, NULL);
 
+    timer_setup();
+
     daemon_setup();
 
     do {
-       now = time(NULL);
+       now = atd_gettime();
        next_invocation = run_loop();
        if (next_invocation > now) {
-           sleep(next_invocation - now);
+           atd_setalarm(next_invocation);
        }
     } while (!term_signal);
     daemon_cleanup();
diff -ur at-3.1.13/config.h.in at-3.1.13.timer/config.h.in
--- at-3.1.13/config.h.in       2011-06-25 08:43:14.000000000 -0400
+++ at-3.1.13.timer/config.h.in 2011-11-16 17:26:02.406420986 -0500
@@ -38,6 +38,9 @@
 /* Define to 1 if you have the `getloadavg' function. */
 #undef HAVE_GETLOADAVG
 
+/* Define to 1 if you have the `clock_gettime' function. */
+#undef HAVE_CLOCK_GETTIME
+
 /* Define to 1 if you have the <getopt.h> header file. */
 #undef HAVE_GETOPT_H
 
diff -ur at-3.1.13/configure.ac at-3.1.13.timer/configure.ac
--- at-3.1.13/configure.ac      2011-06-25 08:43:14.000000000 -0400
+++ at-3.1.13.timer/configure.ac        2011-11-16 17:26:02.407421018 -0500
@@ -259,5 +259,9 @@
 )
 AC_SUBST(DAEMON_GROUPNAME)
 
+dnl check for POSIX timer functions
+AC_SEARCH_LIBS([clock_gettime],[rt])
+AC_CHECK_FUNCS([clock_gettime])
+
 AC_CONFIG_FILES(Makefile atrun atd.8 atrun.8 at.1 at.allow.5 batch)
 AC_OUTPUT

-- 
Matthew Garrett | mj...@srcf.ucam.org

--- End Message ---

Reply via email to