--- a/borgend/scheduler.py Sun Feb 04 14:37:09 2018 +0000 +++ b/borgend/scheduler.py Mon Feb 05 10:25:17 2018 +0000 @@ -12,6 +12,7 @@ from threading import Condition, Thread from . import dreamtime +from .exprotect import protect_noreturn logger=logging.getLogger(__name__) @@ -147,51 +148,46 @@ super().__init__(target = self._scheduler_thread, name = 'Scheduler') dreamtime.add_callback(self, self._sleepwake_callback) + @protect_noreturn def _scheduler_thread(self): logger.debug("Scheduler thread started") with self._cond: while not self._terminate: - try: - self.__schedule_one() - except: - logger.exception("Bug in scheduler") - - def __schedule_one(self): - snapshot = dreamtime.Snapshot() - now = snapshot.monotonic() - if not self._list: - timeout = None - delta = None - nextname = None - else: - nextname=self._list.name - delta = self._list.when.horizon(snapshot)-now - if delta==math.inf: - timeout=None - else: - timeout = min(self.precision, delta) + snapshot = dreamtime.Snapshot() + now = snapshot.monotonic() + if not self._list: + timeout = None + delta = None + nextname = None + else: + nextname=self._list.name + delta = self._list.when.horizon(snapshot)-now + if delta==math.inf: + timeout=None + else: + timeout = min(self.precision, delta) - if not timeout or timeout>0: - logger.debug("Scheduler waiting %s seconds [next event '%s' in %s seconds]" - % (str(timeout), nextname, str(delta))) - self._cond.wait(timeout) - snapshot = dreamtime.Snapshot() - now = snapshot.monotonic() - logger.debug("Scheduler timed out") + if not timeout or timeout>0: + logger.debug("Scheduler waiting %s seconds [next event '%s' in %s seconds]" + % (str(timeout), nextname, str(delta))) + self._cond.wait(timeout) + snapshot = dreamtime.Snapshot() + now = snapshot.monotonic() + logger.debug("Scheduler timed out") - while self._list and self._list.when.horizon(snapshot) <= now: - ev=self._list - logger.debug("Scheduler activating %s" % (ev.name or "(unknown)")) - # We are only allowed to remove ev from list when ev.cond allows - self._unlink(ev) - # We need to release the lock on self._cond before acquire - # one ev.cond to avoid race conditions with self._wait - self._cond.release() - with ev.cond: - ev.cond.notify_all() - self._cond.acquire() + while self._list and self._list.when.horizon(snapshot) <= now: + ev=self._list + logger.debug("Scheduler activating %s" % (ev.name or "(unknown)")) + # We are only allowed to remove ev from list when ev.cond allows + self._unlink(ev) + # We need to release the lock on self._cond before acquire + # one ev.cond to avoid race conditions with self._wait + self._cond.release() + with ev.cond: + ev.cond.notify_all() + self._cond.acquire() - + @protect_noreturn def _sleepwake_callback(self, woke): logger.debug("Rescheduling events after sleep/wakeup") with self._cond: