diff -r a5bbef4205e0 asyncio/base_events.py --- a/asyncio/base_events.py Thu Jan 30 13:07:06 2014 -0800 +++ b/asyncio/base_events.py Fri Jan 31 09:45:31 2014 +0100 @@ -603,38 +603,48 @@ class BaseEventLoop(events.AbstractEvent schedules the resulting callbacks, and finally schedules 'call_later' callbacks. """ - # Remove delayed calls that were cancelled from head of queue. - while self._scheduled and self._scheduled[0]._cancelled: - heapq.heappop(self._scheduled) + while True: + # Remove delayed calls that were cancelled from head of queue. + while self._scheduled and self._scheduled[0]._cancelled: + heapq.heappop(self._scheduled) - timeout = None - if self._ready: - timeout = 0 - elif self._scheduled: - # Compute the desired timeout. - when = self._scheduled[0]._when - deadline = max(0, when - self.time()) - if timeout is None: - timeout = deadline + timeout = None + if self._ready: + timeout = 0 + elif self._scheduled: + # Compute the desired timeout. + when = self._scheduled[0]._when + deadline = max(0, when - self.time()) + if timeout is None: + timeout = deadline + else: + timeout = min(timeout, deadline) + + # TODO: Instrumentation only in debug mode? + if logger.isEnabledFor(logging.INFO): + t0 = self.time() + event_list = self._selector.select(timeout) + t1 = self.time() + if t1-t0 >= 1: + level = logging.INFO + else: + level = logging.DEBUG + if timeout is not None: + logger.log(level, 'poll %.3f took %.3f seconds', + timeout, t1-t0) + else: + logger.log(level, 'poll took %.3f seconds', t1-t0) else: - timeout = min(timeout, deadline) + event_list = self._selector.select(timeout) + if event_list or self._ready: + break + if self._scheduled: + now = self.time() + self._granularity + if self._scheduled[0]._when <= now: + break + # selector was interrupted by a signal, or the granularity + # is wrong (too precise) and the selector took less than timeout - # TODO: Instrumentation only in debug mode? - if logger.isEnabledFor(logging.INFO): - t0 = self.time() - event_list = self._selector.select(timeout) - t1 = self.time() - if t1-t0 >= 1: - level = logging.INFO - else: - level = logging.DEBUG - if timeout is not None: - logger.log(level, 'poll %.3f took %.3f seconds', - timeout, t1-t0) - else: - logger.log(level, 'poll took %.3f seconds', t1-t0) - else: - event_list = self._selector.select(timeout) self._process_events(event_list) # Handle 'later' callbacks that are ready.