On Fri, Oct 13, 2017 at 11:25:41AM +0200, Jesper Wallin wrote:
> On Thu, Oct 12, 2017 at 08:42:44PM +0000, Mark Lee Smith wrote:
> > As the -t option appears to have been available in previous releases so I
> > suspect this bug has existed for some time, and effects more than just the
> > new autoactions, although what it might effect I can't say.
> > 
> > I hope that I've managed to provide enough information to confirm that a
> > bug exists and gone some way to helping isolate it.
> > 
> > All the best,
> > 
> > Mark
> 
> Hi Mark,
> 
> I just realized that I've always used apmd with -t 10 and thus never had
> any issue with this.  I've did a bit of testing now and as far as I can
> tell, apmtimeout is sometimes incorrect as the loop doesn't iterate
> every second.
> 
> The patch below uses a time() timestamp instead and compares it to the
> time when last iteration occured.  This may not be the best solutions
> considering suspending/resuming and the clock might be off. The quick
> fix for this is to simply reset the timestamp if things seems off and
> the worst-case scenario is that we poll an extra time.

How about using the monotonic clock instead. I don't use the feature
myself but tested once with the default poll interval. It did suspend
and upon immediate resume, it took approximately another poll interval
(10 minutes) before a second suspend was triggered.

Index: apmd.c
===================================================================
RCS file: /cvs/src/usr.sbin/apmd/apmd.c,v
retrieving revision 1.81
diff -u -p -r1.81 apmd.c
--- apmd.c      15 Oct 2017 15:14:49 -0000      1.81
+++ apmd.c      23 Oct 2017 08:38:18 -0000
@@ -354,8 +354,8 @@ main(int argc, char *argv[])
        int powerstatus = 0, powerbak = 0, powerchange = 0;
        int noacsleep = 0;
        struct timespec ts = {TIMO, 0}, sts = {0, 0};
+       struct timespec apmtimeout, now;
        struct apm_power_info pinfo;
-       time_t apmtimeout = 0;
        const char *sockname = sockfile;
        const char *errstr;
        int kq, nchanges;
@@ -473,6 +473,8 @@ main(int argc, char *argv[])
                    EV_CLEAR, 0, 0, NULL);
                nchanges = 2;
        }
+       if (clock_gettime(CLOCK_MONOTONIC, &apmtimeout) == -1)
+               timespecclear(&apmtimeout);
        if (kevent(kq, ev, nchanges, NULL, 0, &sts) < 0)
                error("kevent", NULL);
 
@@ -484,12 +486,12 @@ main(int argc, char *argv[])
 
                sts = ts;
 
-               apmtimeout += 1;
                if ((rv = kevent(kq, NULL, 0, ev, 1, &sts)) < 0)
                        break;
 
-               if (apmtimeout >= ts.tv_sec) {
-                       apmtimeout = 0;
+               if (clock_gettime(CLOCK_MONOTONIC, &now) == 0 &&
+                   now.tv_sec - apmtimeout.tv_sec >= ts.tv_sec) {
+                       apmtimeout = now;
 
                        /* wakeup for timeout: take status */
                        powerbak = power_status(ctl_fd, 0, &pinfo);

Reply via email to