diff --git a/lib/daemon.py b/lib/daemon.py
index e0ab16cb476f74bb1d4e625372b5755ee6c4cd75..860e3640658fee6d9c436ae836ec70ca40249254 100644
--- a/lib/daemon.py
+++ b/lib/daemon.py
@@ -28,9 +28,47 @@ import select
 import signal
 import errno
 import logging
+import sched
+import time
 
 from ganeti import utils
 from ganeti import constants
+from ganeti import errors
+
+
+class SchedulerBreakout(Exception):
+  """Exception used to get out of the scheduler loop
+
+  """
+
+
+def AsyncoreDelayFunction(timeout):
+  """Asyncore-compatible scheduler delay function.
+
+  This is a delay function for sched that, rather than actually sleeping,
+  executes asyncore events happening in the meantime.
+
+  After an event has occurred, rather than returning, it raises a
+  SchedulerBreakout exception, which will force the current scheduler.run()
+  invocation to terminate, so that we can also check for signals. The main loop
+  will then call the scheduler run again, which will allow it to actually
+  process any due events.
+
+  This is needed because scheduler.run() doesn't support a count=..., as
+  asyncore loop, and the scheduler module documents throwing exceptions from
+  inside the delay function as an allowed usage model.
+
+  """
+  asyncore.loop(timeout=timeout, count=1, use_poll=True)
+  raise SchedulerBreakout()
+
+
+class AsyncoreScheduler(sched.scheduler):
+  """Event scheduler integrated with asyncore
+
+  """
+  def __init__(self, timefunc):
+    sched.scheduler.__init__(self, timefunc, AsyncoreDelayFunction)
 
 
 class Mainloop(object):
@@ -40,8 +78,12 @@ class Mainloop(object):
   def __init__(self):
     """Constructs a new Mainloop instance.
 
+    @ivar scheduler: A L{sched.scheduler} object, which can be used to register
+    timed events
+
     """
     self._signal_wait = []
+    self.scheduler = AsyncoreScheduler(time.time)
 
   @utils.SignalHandled([signal.SIGCHLD])
   @utils.SignalHandled([signal.SIGTERM])
@@ -65,7 +107,13 @@ class Mainloop(object):
       if stop_on_empty and not (self._io_wait):
         break
 
-      asyncore.loop(timeout=5, count=1, use_poll=True)
+      if not self.scheduler.empty():
+        try:
+          self.scheduler.run()
+        except SchedulerBreakout:
+          pass
+      else:
+        asyncore.loop(count=1, use_poll=True)
 
       # Check whether a signal was raised
       for sig in signal_handlers: