# HG changeset patch # User Tuomo Valkonen # Date 1517948219 0 # Node ID c3bc27cf5ecea804fb02ab9bbb837b7ddd829450 # Parent a79409c72565baccfb3ee53b6996a516b6a64ba3 Changed dreamtime calculation. The monotonic clock (time.monotonic()) sometimes advances unreliably in sleep, so isn't reliable for calculating sleeping time. We have to use time.time(). But this may be changed by the user, so we only use it to track sleep periods, and still use time.monotonic() to track wake periods. diff -r a79409c72565 -r c3bc27cf5ece borgend/dreamtime.py --- a/borgend/dreamtime.py Tue Feb 06 08:30:20 2018 +0000 +++ b/borgend/dreamtime.py Tue Feb 06 20:16:59 2018 +0000 @@ -215,10 +215,16 @@ class SleepHandler(Foundation.NSObject): """ Handle wake/sleep notifications """ + # We need to use the actual time.time() to monitor sleep, as + # time.monotonic() many not run during sleep. But time.time() + # may encounter adjustments, so we also use time.monotonic() to + # monitor wake periods. + def init(self): self.__sleeptime=None - self.__slept=0 - self.__epoch=time.monotonic() + self.__dreamtime_last_sleep=0 + self.__monotonic_last_wakeup=time.monotonic() + self.__slept=0 # Only used to store the statistic self.__lock=threading.Lock() self.__callbacks=weakref.WeakKeyDictionary() @@ -227,18 +233,21 @@ @protect_noreturn def handleSleepNotification_(self, aNotification): logger.info("System going to sleep") - now=time.monotonic() with self.__lock: - self.__sleeptime=now + self.__sleeptime=time.time() + now_m=time.monotonic() + self.__dreamtime_last_sleep=(self.__dreamtime_last_sleep+now_m + -self.__monotonic_last_wakeup) callbacks=self.__callbacks.copy() do_callbacks(callbacks, False) @protect_noreturn def handleWakeNotification_(self, aNotification): logger.info("System waking up from sleep") - now=time.monotonic() with self.__lock: if self.__sleeptime: + self.__monotonic_last_wakeup=time.monotonic() + now=time.time() slept=max(0, now-self.__sleeptime) logger.info("Slept %f seconds" % slept) self.__slept=self.__slept+slept @@ -248,7 +257,6 @@ # Return dreamtime def dreamtime_sleeping(self, snapshot=Snapshot()): - sleeping=False with self.__lock: # macOS "sleep" signals / status are complete bollocks: at least # when plugged in, the system is actually sometimes running all @@ -256,11 +264,13 @@ # Therefore, we need our timers to work in a sane manner when # we should be sleeping! if self.__sleeptime is not None: - now_monotonic=self.__sleeptime sleeping=True + now_dreamtime=self.__dreamtime_last_sleep else: - now_monotonic=snapshot.monotonic() - now_dreamtime=max(0, now_monotonic-self.__epoch-self.__slept) + sleeping=False + now=snapshot.monotonic() + now_dreamtime=(self.__dreamtime_last_sleep + +now-self.__monotonic_last_wakeup); return now_dreamtime, sleeping # Weirdo (Py)ObjC naming to stop it form choking up diff -r a79409c72565 -r c3bc27cf5ece borgend/ui.py --- a/borgend/ui.py Tue Feb 06 08:30:20 2018 +0000 +++ b/borgend/ui.py Tue Feb 06 20:16:59 2018 +0000 @@ -129,7 +129,7 @@ diff=datetime.timedelta(seconds=when-now) if twhentendtomorrow: # Display date if scheduled event is after tomorrow whenday=datetime.date.fromtimestamp(when)