diff --git a/daemons/ganeti-confd b/daemons/ganeti-confd
index 958e1a133e50948250b38f899628b0d668e72846..3a685c78e2682eeda7eb46d0e26664b5df003ca2 100755
--- a/daemons/ganeti-confd
+++ b/daemons/ganeti-confd
@@ -117,7 +117,8 @@ class ConfdConfigurationReloader(object):
     self.inotify_handler = asyncnotifier.SingleFileEventHandler(self.wm,
                                                                 self.OnInotify,
                                                                 cfg_file)
-    self.notifier = asyncnotifier.AsyncNotifier(self.wm, self.inotify_handler)
+    notifier_class = asyncnotifier.ErrorLoggingAsyncNotifier
+    self.notifier = notifier_class(self.wm, self.inotify_handler)
 
     self.timer_handle = None
     self._EnableTimer()
diff --git a/lib/asyncnotifier.py b/lib/asyncnotifier.py
index 421e476dba9de643556d934ccc7482e6e0952fb1..e60c26087557a0c96cd067418b3c9ab696b9dd83 100644
--- a/lib/asyncnotifier.py
+++ b/lib/asyncnotifier.py
@@ -31,6 +31,7 @@ try:
 except ImportError:
   import pyinotify
 
+from ganeti import daemon
 from ganeti import errors
 
 # We contributed the AsyncNotifier class back to python-pyinotify, and it's
@@ -65,6 +66,16 @@ class AsyncNotifier(asyncore.file_dispatcher):
     self.notifier.process_events()
 
 
+class ErrorLoggingAsyncNotifier(AsyncNotifier,
+                                daemon.GanetiBaseAsyncoreDispatcher):
+  """An asyncnotifier that can survive errors in the callbacks.
+
+  We define this as a separate class, since we don't want to make AsyncNotifier
+  diverge from what we contributed upstream.
+
+  """
+
+
 class SingleFileEventHandler(pyinotify.ProcessEvent):
   """Handle modify events for a single file.
 
@@ -122,14 +133,7 @@ class SingleFileEventHandler(pyinotify.ProcessEvent):
     # by the callback by calling "enable" again on us.
     logging.debug("Received 'ignored' inotify event for %s", event.path)
     self.watch_handle = None
-
-    try:
-      self.callback(False)
-    except: # pylint: disable-msg=W0702
-      # we need to catch any exception here, log it, but proceed, because even
-      # if we failed handling a single request, we still want our daemon to
-      # proceed.
-      logging.error("Unexpected exception", exc_info=True)
+    self.callback(False)
 
   # pylint: disable-msg=C0103
   # this overrides a method in pyinotify.ProcessEvent
@@ -139,14 +143,7 @@ class SingleFileEventHandler(pyinotify.ProcessEvent):
     # replacing any file with a new one, at filesystem level, rather than
     # actually changing it. (see utils.WriteFile)
     logging.debug("Received 'modify' inotify event for %s", event.path)
-
-    try:
-      self.callback(True)
-    except: # pylint: disable-msg=W0702
-      # we need to catch any exception here, log it, but proceed, because even
-      # if we failed handling a single request, we still want our daemon to
-      # proceed.
-      logging.error("Unexpected exception", exc_info=True)
+    self.callback(True)
 
   def process_default(self, event):
     logging.error("Received unhandled inotify event: %s", event)
diff --git a/lib/daemon.py b/lib/daemon.py
index 8a057a0f3cf83b08a9cc8a3817815a7f6c1367fb..21aab9227c42a49c3542421535d9ad31c3a3b719 100644
--- a/lib/daemon.py
+++ b/lib/daemon.py
@@ -72,7 +72,26 @@ class AsyncoreScheduler(sched.scheduler):
     sched.scheduler.__init__(self, timefunc, AsyncoreDelayFunction)
 
 
-class AsyncUDPSocket(asyncore.dispatcher):
+class GanetiBaseAsyncoreDispatcher(asyncore.dispatcher):
+  """Base Ganeti Asyncore Dispacher
+
+  """
+  # this method is overriding an asyncore.dispatcher method
+  def handle_error(self):
+    """Log an error in handling any request, and proceed.
+
+    """
+    logging.exception("Error while handling asyncore request")
+
+  # this method is overriding an asyncore.dispatcher method
+  def writable(self):
+    """Most of the time we don't want to check for writability.
+
+    """
+    return False
+
+
+class AsyncUDPSocket(GanetiBaseAsyncoreDispatcher):
   """An improved asyncore udp socket.
 
   """
@@ -80,7 +99,7 @@ class AsyncUDPSocket(asyncore.dispatcher):
     """Constructor for AsyncUDPSocket
 
     """
-    asyncore.dispatcher.__init__(self)
+    GanetiBaseAsyncoreDispatcher.__init__(self)
     self._out_queue = []
     self.create_socket(socket.AF_INET, socket.SOCK_DGRAM)
 
@@ -119,13 +138,6 @@ class AsyncUDPSocket(asyncore.dispatcher):
     utils.IgnoreSignals(self.sendto, payload, 0, (ip, port))
     self._out_queue.pop(0)
 
-  # this method is overriding an asyncore.dispatcher method
-  def handle_error(self):
-    """Log an error in handling any request, and proceed.
-
-    """
-    logging.exception("Error while handling asyncore request")
-
   def enqueue_send(self, ip, port, payload):
     """Enqueue a datagram to be sent when possible
 
diff --git a/test/ganeti.asyncnotifier_unittest.py b/test/ganeti.asyncnotifier_unittest.py
index b379ba1efff8d77f459938d8a8f4f6552be3c995..51b3a82c470003b542a15e023980d20efec090ad 100755
--- a/test/ganeti.asyncnotifier_unittest.py
+++ b/test/ganeti.asyncnotifier_unittest.py
@@ -34,14 +34,27 @@ except ImportError:
 from ganeti import asyncnotifier
 from ganeti import daemon
 from ganeti import utils
+from ganeti import errors
 
 import testutils
 
 
+class _MyErrorLoggingAsyncNotifier(asyncnotifier.ErrorLoggingAsyncNotifier):
+  def __init__(self, *args, **kwargs):
+    asyncnotifier.ErrorLoggingAsyncNotifier.__init__(self, *args, **kwargs)
+    self.error_count = 0
+
+  def handle_error(self):
+    self.error_count += 1
+    # We should also terminate while handling an error, so that any unexpected
+    # error is registered and can be checked.
+    os.kill(os.getpid(), signal.SIGTERM)
+
+
 class TestSingleFileEventHandler(testutils.GanetiTestCase):
   """Test daemon.Mainloop"""
 
-  NOTIFIERS = [NOTIFIER_TERM, NOTIFIER_NORM] = range(2)
+  NOTIFIERS = [NOTIFIER_TERM, NOTIFIER_NORM, NOTIFIER_ERR] = range(3)
 
   def setUp(self):
     testutils.GanetiTestCase.setUp(self)
@@ -57,8 +70,8 @@ class TestSingleFileEventHandler(testutils.GanetiTestCase):
                                                           self.cbk[i],
                                                           self.chk_files[i])
                       for i in range(len(self.NOTIFIERS))]
-    self.notifiers = [asyncnotifier.AsyncNotifier(self.wms[i],
-                                                  self.ihandler[i])
+    self.notifiers = [_MyErrorLoggingAsyncNotifier(self.wms[i],
+                                                   self.ihandler[i])
                        for i in range(len(self.NOTIFIERS))]
     # TERM notifier is enabled by default, as we use it to get out of the loop
     self.ihandler[self.NOTIFIER_TERM].enable()
@@ -73,12 +86,16 @@ class TestSingleFileEventHandler(testutils.GanetiTestCase):
       self.notified[self.i] = True
       if self.i == self.testobj.NOTIFIER_TERM:
         os.kill(os.getpid(), signal.SIGTERM)
+      elif self.i == self.testobj.NOTIFIER_ERR:
+        raise errors.GenericError("an error")
 
   def testReplace(self):
     utils.WriteFile(self.chk_files[self.NOTIFIER_TERM], data="dummy")
     self.mainloop.Run()
     self.assert_(self.notified[self.NOTIFIER_TERM])
     self.assert_(not self.notified[self.NOTIFIER_NORM])
+    self.assertEquals(self.notifiers[self.NOTIFIER_TERM].error_count, 0)
+    self.assertEquals(self.notifiers[self.NOTIFIER_NORM].error_count, 0)
 
   def testEnableDisable(self):
     self.ihandler[self.NOTIFIER_TERM].enable()
@@ -91,6 +108,8 @@ class TestSingleFileEventHandler(testutils.GanetiTestCase):
     self.mainloop.Run()
     self.assert_(self.notified[self.NOTIFIER_TERM])
     self.assert_(not self.notified[self.NOTIFIER_NORM])
+    self.assertEquals(self.notifiers[self.NOTIFIER_TERM].error_count, 0)
+    self.assertEquals(self.notifiers[self.NOTIFIER_NORM].error_count, 0)
 
   def testDoubleEnable(self):
     self.ihandler[self.NOTIFIER_TERM].enable()
@@ -99,6 +118,8 @@ class TestSingleFileEventHandler(testutils.GanetiTestCase):
     self.mainloop.Run()
     self.assert_(self.notified[self.NOTIFIER_TERM])
     self.assert_(not self.notified[self.NOTIFIER_NORM])
+    self.assertEquals(self.notifiers[self.NOTIFIER_TERM].error_count, 0)
+    self.assertEquals(self.notifiers[self.NOTIFIER_NORM].error_count, 0)
 
   def testDefaultDisabled(self):
     utils.WriteFile(self.chk_files[self.NOTIFIER_NORM], data="dummy")
@@ -107,6 +128,8 @@ class TestSingleFileEventHandler(testutils.GanetiTestCase):
     self.assert_(self.notified[self.NOTIFIER_TERM])
     # NORM notifier is disabled by default
     self.assert_(not self.notified[self.NOTIFIER_NORM])
+    self.assertEquals(self.notifiers[self.NOTIFIER_TERM].error_count, 0)
+    self.assertEquals(self.notifiers[self.NOTIFIER_NORM].error_count, 0)
 
   def testBothEnabled(self):
     self.ihandler[self.NOTIFIER_NORM].enable()
@@ -115,6 +138,17 @@ class TestSingleFileEventHandler(testutils.GanetiTestCase):
     self.mainloop.Run()
     self.assert_(self.notified[self.NOTIFIER_TERM])
     self.assert_(self.notified[self.NOTIFIER_NORM])
+    self.assertEquals(self.notifiers[self.NOTIFIER_TERM].error_count, 0)
+    self.assertEquals(self.notifiers[self.NOTIFIER_NORM].error_count, 0)
+
+  def testError(self):
+    self.ihandler[self.NOTIFIER_ERR].enable()
+    utils.WriteFile(self.chk_files[self.NOTIFIER_ERR], data="dummy")
+    self.mainloop.Run()
+    self.assert_(self.notified[self.NOTIFIER_ERR])
+    self.assertEquals(self.notifiers[self.NOTIFIER_ERR].error_count, 1)
+    self.assertEquals(self.notifiers[self.NOTIFIER_NORM].error_count, 0)
+    self.assertEquals(self.notifiers[self.NOTIFIER_TERM].error_count, 0)
 
 
 if __name__ == "__main__":