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);