diff --git a/Console/Readline.cc b/Console/Readline.cc
index 094c8e40c597cf4593c4e564aab193af082e283f..f1597d4d759f3b13f0cddf18a6a448b1bbf5af7a 100644
--- a/Console/Readline.cc
+++ b/Console/Readline.cc
@@ -198,7 +198,7 @@ prefix_ void senf::console::detail::ReadlineClientReader::v_translate(std::strin
     boost::replace_all(data, "\xff", "\xff\xff");
 }
 
-prefix_ void senf::console::detail::ReadlineClientReader::charEvent(Scheduler::EventId event)
+prefix_ void senf::console::detail::ReadlineClientReader::charEvent(int event)
 {
     char ch;
     if (event != Scheduler::EV_READ || handle().read(&ch, &ch+1) <= &ch) {
diff --git a/Console/Readline.hh b/Console/Readline.hh
index 00372d74071e311742c976c4fb20bc88c8b4c64a..09a9e61c8a7fd09e09ecaea54e43eabc8095c73f 100644
--- a/Console/Readline.hh
+++ b/Console/Readline.hh
@@ -72,7 +72,7 @@ namespace detail {
         virtual void v_enablePrompt();
         virtual void v_translate(std::string & data);
 
-        void charEvent(Scheduler::EventId event);
+        void charEvent(int event);
 
         static ReadlineClientReader * instance_;
         int ch_;
diff --git a/Console/Server.cc b/Console/Server.cc
index dc169fa898a17cc57d3f8a57ce03bfd7327ca7d8..3ef80ba1321aa2bc6add9a870a023a6603889cd8 100644
--- a/Console/Server.cc
+++ b/Console/Server.cc
@@ -104,7 +104,7 @@ prefix_ senf::console::Server::~Server()
     Scheduler::instance().remove(handle_);
 }
 
-prefix_ void senf::console::Server::newClient(Scheduler::EventId event)
+prefix_ void senf::console::Server::newClient(int event)
 {
     ServerHandle::ClientSocketHandle client (handle_.accept());
     boost::intrusive_ptr<Client> p (new Client(*this, client));
@@ -200,7 +200,7 @@ prefix_ void senf::console::detail::NoninteractiveClientReader::v_translate(std:
 {}
 
 prefix_ void
-senf::console::detail::NoninteractiveClientReader::newData(senf::Scheduler::EventId event)
+senf::console::detail::NoninteractiveClientReader::newData(int event)
 {
     if (event != senf::Scheduler::EV_READ || handle().eof()) {
         if (! buffer_.empty())
diff --git a/Console/Server.cci b/Console/Server.cci
index e4601f67c915d9d0358f11dd13fdac7fcec89101..81aaf6de0040f5ad04ad16359437455732926c04 100644
--- a/Console/Server.cci
+++ b/Console/Server.cci
@@ -43,6 +43,12 @@ prefix_ void senf::console::detail::ServerManager::remove(ptr server)
     instance().servers_.erase(instance().servers_.find(server));
 }
 
+prefix_ senf::console::detail::ServerManager & senf::console::detail::ServerManager::instance()
+{
+    static ServerManager manager;
+    return manager;
+}
+
 ///////////////////////////////////////////////////////////////////////////
 // senf::console::detail::NonblockingSocketSink
 
diff --git a/Console/Server.hh b/Console/Server.hh
index 1756e14717b3fb79164ddf869691c1ffda1f69be..b7684d56a9000b01386167bc3b7da5897016035b 100644
--- a/Console/Server.hh
+++ b/Console/Server.hh
@@ -129,7 +129,7 @@ namespace console {
 
         static Server & start(ServerHandle handle);
 
-        void newClient(Scheduler::EventId event);
+        void newClient(int event);
         void removeClient(Client & client);
         
         ServerHandle handle_;
diff --git a/Console/Server.ih b/Console/Server.ih
index 925fd64d01dacb4738d0a5b6e244539675b9e071..3ca80a1db80803acdebc3e312273e40a82cb7367 100644
--- a/Console/Server.ih
+++ b/Console/Server.ih
@@ -42,7 +42,6 @@ namespace console {
 namespace detail {
 
     class ServerManager
-        : public senf::singleton<ServerManager>
     {
     public:
         typedef boost::intrusive_ptr<Server> ptr;
@@ -53,6 +52,8 @@ namespace detail {
         static void add(ptr server);
         static void remove(ptr server);
 
+        static ServerManager & instance();
+
         typedef std::set<ptr> Servers;
         Servers servers_;
 
@@ -170,7 +171,7 @@ namespace detail {
         virtual void v_enablePrompt();
         virtual void v_translate(std::string & data);
 
-        void newData(senf::Scheduler::EventId event);
+        void newData(int event);
 
         SchedulerBinding binding_;
         std::string buffer_;
diff --git a/Examples/MCSniffer/MCSniffer.cc b/Examples/MCSniffer/MCSniffer.cc
index 896ef3ad904adf461ec6a028e29c36992d2d0335..211ebaf508b9c6ac2dde3884e1b3fcc1f6e8e622 100644
--- a/Examples/MCSniffer/MCSniffer.cc
+++ b/Examples/MCSniffer/MCSniffer.cc
@@ -57,7 +57,7 @@ public:
     }
 
 private:
-    void dumpPacket(senf::Scheduler::EventId event)
+    void dumpPacket(int event)
     {
         std::string data (sock.read());
         senf::EthernetPacket packet (
diff --git a/Examples/Sniffer/Sniffer.cc b/Examples/Sniffer/Sniffer.cc
index fbeeab4c3e3398e0f3e88986859208037f44d2ab..7f748068280c426f484b61b814ac112d6e8fb512 100644
--- a/Examples/Sniffer/Sniffer.cc
+++ b/Examples/Sniffer/Sniffer.cc
@@ -82,7 +82,7 @@ public:
     }
 
 private:
-    void dumpPacket(senf::Scheduler::EventId event)
+    void dumpPacket(int event)
     {
         senf::EthernetPacket packet (
             senf::EthernetPacket::create(senf::noinit));
diff --git a/Examples/TCPClientServer/server.cc b/Examples/TCPClientServer/server.cc
index 93fb1baf05b6f1ad177e7c8e705192fc08548992..4dbf274e0a500306a6f4907ce066eba32dfaec13 100644
--- a/Examples/TCPClientServer/server.cc
+++ b/Examples/TCPClientServer/server.cc
@@ -50,7 +50,7 @@ public:
     }
 
 private:
-    void accept(senf::Scheduler::EventId event)
+    void accept(int event)
     {
         senf::TCPv4ClientSocketHandle clientSock (serverSock.accept());
         senf::Scheduler::instance().add(
@@ -59,7 +59,7 @@ private:
             senf::Scheduler::EV_READ);
     }
 
-    void readFromClient(senf::TCPv4ClientSocketHandle clientSock, senf::Scheduler::EventId event)
+    void readFromClient(senf::TCPv4ClientSocketHandle clientSock, int event)
     {
         if (!clientSock) {
             senf::Scheduler::instance().remove(clientSock);
diff --git a/Examples/UDPClientServer/udpServer.cc b/Examples/UDPClientServer/udpServer.cc
index 091b6ba8e3e8a14b59620754b7e09db6ab717c0c..d549a92e4afa6efe0b51123c15bde94170cb2d8a 100644
--- a/Examples/UDPClientServer/udpServer.cc
+++ b/Examples/UDPClientServer/udpServer.cc
@@ -44,7 +44,7 @@ public:
     }
 
 private:
-    void readFromClient(senf::Scheduler::EventId event)
+    void readFromClient(int event)
     {
         std::string data (serverSock.read());
         std::cout << "> " << data<<std::endl ;
diff --git a/PPI/ActiveFeeder.hh b/PPI/ActiveFeeder.hh
index f9c7ed7a6d95b5c1e750b3cd2ca8029a409172f7..494f1eadca020713ae82274ff074cd2033349627 100644
--- a/PPI/ActiveFeeder.hh
+++ b/PPI/ActiveFeeder.hh
@@ -40,7 +40,7 @@ namespace module {
 
     /** \brief Adapter to connect passive connectors
 
-        ActiveFeeder is an adapter module which allows to connect to passive connectors. As long as
+        ActiveFeeder is an adapter module which allows two connect to passive connectors. As long as
         none of the connectors is throttled, the ActiveFeeder will forward packets from it's input
         to it's output.
 
diff --git a/PPI/IOEvent.cc b/PPI/IOEvent.cc
index c39d57a1f93c4b9e2d4e90cf36458eac98fef08b..73bcc5f68417997782929cd4f43b4ddabfedbf41 100644
--- a/PPI/IOEvent.cc
+++ b/PPI/IOEvent.cc
@@ -51,7 +51,7 @@ prefix_ void senf::ppi::IOEvent::v_disable()
     Scheduler::instance().remove(fd_, Scheduler::EventId(events_));
 }
 
-prefix_ void senf::ppi::IOEvent::cb(Scheduler::EventId event)
+prefix_ void senf::ppi::IOEvent::cb(int event)
 {
     if ((event & ~events_) != 0) {
         if (event & Err)
diff --git a/PPI/IOEvent.hh b/PPI/IOEvent.hh
index d2f952819a3fb89806b3ddecef3663066e5b47c7..77c5d26c190b08f5188685380d4da4a4173a983a 100644
--- a/PPI/IOEvent.hh
+++ b/PPI/IOEvent.hh
@@ -108,7 +108,7 @@ namespace ppi {
         virtual void v_enable();
          virtual void v_disable();
         
-        void cb(Scheduler::EventId event);
+        void cb(int event);
 
         int fd_;
         unsigned events_;
diff --git a/PPI/IdleEvent.cc b/PPI/IdleEvent.cc
index d3346857b26eafa7069f2025fbfbb94d961fc828..37077bbd16d8edcafec0aeb9eac5a78c68987378 100644
--- a/PPI/IdleEvent.cc
+++ b/PPI/IdleEvent.cc
@@ -28,6 +28,7 @@
 
 // Custom includes
 #include "../Scheduler/Scheduler.hh"
+#include "../Utils/Logger/SenfLog.hh"
 
 //#include "IdleEvent.mpp"
 #define prefix_
diff --git a/Scheduler/ClockService.cci b/Scheduler/ClockService.cci
index c24b736c365e6bc37c22df90a4226189d3b89458..3c159550b094320a4805245e9c5b1c29d48d0355 100644
--- a/Scheduler/ClockService.cci
+++ b/Scheduler/ClockService.cci
@@ -47,6 +47,8 @@ prefix_ senf::ClockService::clock_type senf::ClockService::now()
 
 prefix_ senf::ClockService::clock_type senf::ClockService::clock_m(abstime_type time)
 {
+    if (now() - baseClock_ > 1000000000ll)
+        restart_m();
     boost::posix_time::time_duration delta (time - baseAbstime_);
     return baseClock_ + clock_type( delta.ticks() )
         * clock_type( 1000000000UL / boost::posix_time::time_duration::ticks_per_second() );
@@ -54,6 +56,8 @@ prefix_ senf::ClockService::clock_type senf::ClockService::clock_m(abstime_type
 
 prefix_ senf::ClockService::abstime_type senf::ClockService::abstime_m(clock_type clock)
 {
+    if (now() - baseClock_ > 1000000000ll)
+        restart_m();
 #ifdef BOOST_DATE_TIME_POSIX_TIME_STD_CONFIG
     return baseAbstime_ + boost::posix_time::nanoseconds(clock-baseClock_);
 #else
diff --git a/Scheduler/ClockService.hh b/Scheduler/ClockService.hh
index da50573e35b335826ffc321999c7f0ba94fb4655..5b02c19088c3a601464c09d0ccf38709d0e84893 100644
--- a/Scheduler/ClockService.hh
+++ b/Scheduler/ClockService.hh
@@ -43,55 +43,21 @@ namespace senf {
     namespace detail { class ClockServiceTest; }
 #endif
 
-    // Implementation note:
+    // Implementation note: The clock value is represented as a 64bit unsigned integer number of
+    // nanosecods based on the CLOCK_MONOTONIC POSIX clock.
     //
-    // The clock value is represented as a 64bit unsigned integer number of nanosecods elapsed since
-    // the construction of the ClockService object. 
-    // 
-    // The implementation must provide two features:
-    // a) It must reliably detect clock changes
-    // b) In case of a clock change a reasonably accurate fallback clock value must be provided
-    //
-    // We do this using setitimer/getitimer. We setup an interval timer sending SIGALRM whenever
-    // CheckInverval seconds have elapsed.
-    //
-    // On every SIGALRM signal we save the current value of gettimeofday(). If this new value is
-    // substantially different from the currently saved value + CheckInterval, the clock has been
-    // changed.
-    //
-    // Whenever the current clock value is requested using now(), the current gettimeofday() value
-    // is compared with the saved value. If the difference is substantially more than CheckInterval,
-    // the clock has been changed.
-    //
-    // This provides clock skew detection. If clock skew is detected, we need to move base_ by the
-    // amount the time has been changed. To do this we need an as accurate as possible approximation
-    // of the expected current time value. We need to differentiate two cases:
-    //
-    // a) Clock skew detected within now()
-    //
-    // In this case, we use getitimer() to find the time remaining in the timer. Using this value
-    // and the saved gettimeofday() value we can adjust base_ accordingly.
-    //
-    // b) Clock skew detected in the signal handler
-    //
-    // In this case we use the saved gettimeofday() value + CheckInterval to adjust base_.
+    // To allow conversion between clock value and absolute time, the ClockService samples the
+    // absolute current time and the clock value when the conversion is performed. This is done at
+    // most once per second on a if-needed basis.
     
     /** \brief Reliable high precision monotonous clock source
 
         The ClockService provides a highly accurate monotonous clock source based on
         gettimeofday(). However, it takes additional precautions to detect clock skew.
 
-        \implementation We use a mix of static and non-static members to achieve high performance
-            in the normal case (no clock skew) and still encapsulate the dependency on legacy C
-            headers. Using the senf::singleton mixin ensures, that the instance is constructed
-            before main even when instance() is not called.
-
-        \bug There is a deadlock condition between ClockService and the streaming of Boost.DateTime
-            values: Boost.DateTime seems to call tzset() whenever writing a date/time value (ugh)
-            and since tzset changes basic date/time values, it seems to block gettimeofday() which
-            leads to the SIGLARM handler blocking indefinitely. Resolution either a) find out, why
-            tzset() of all functions is called or b) move the ClockService heartbeat functionality
-            into the Scheduler.
+        \implementation The funny mixture of static and non-static members stems from the old
+            implementation based on interval timers and gettimeofday(). The current implementation
+            usses POSIX clocks and is much simpler and more precise.
       */
     class ClockService
         : singleton<ClockService>
@@ -106,6 +72,11 @@ namespace senf {
             nanoseconds relative to some implementation defined reference time.
          */
         typedef boost::int_fast64_t clock_type;
+
+        /** \brief Supplementary integer type
+
+            This type is used to represent varies supplementary values (e.g. number of microseconds)
+         */
         typedef boost::int_fast64_t int64_type;
 
         /** \brief Absolute time data type
@@ -157,7 +128,10 @@ namespace senf {
         static int64_type in_hours(clock_type v); ///< Convert \a v to hours
         static int64_type in_days(clock_type v); ///< Convert \a v to days
 
-        static void restart();
+        static void restart(); ///< Force re-syncronisation of abstime and clock
+                                        /**< Calling the member should never be necessary since
+                                             abstime() / clock() automatically call restart() if
+                                             needed */
 
     private:
         ClockService();
diff --git a/Scheduler/FIFORunner.cc b/Scheduler/FIFORunner.cc
index 169bcf82b21f80537caca00ac04b03753b0081a9..10cfdc2facc0ea84764703227ce8e84e05742766 100644
--- a/Scheduler/FIFORunner.cc
+++ b/Scheduler/FIFORunner.cc
@@ -27,16 +27,50 @@
 //#include "FIFORunner.ih"
 
 // Custom includes
+#include <signal.h>
+#include <time.h>
+#include "../Utils/Exception.hh"
 
 //#include "FIFORunner.mpp"
 #define prefix_
 ///////////////////////////////cc.p////////////////////////////////////////
 
+prefix_ senf::scheduler::FIFORunner::FIFORunner()
+    : tasks_ (), next_ (tasks_.end()), hangCount_ (0)
+{
+    struct sigevent ev;
+    ::memset(&ev, 0, sizeof(ev));
+    ev.sigev_notify = SIGEV_SIGNAL;
+    ev.sigev_signo = SIGURG;
+    ev.sigev_value.sival_ptr = this;
+    if (timer_create(CLOCK_MONOTONIC, &ev, &watchdogId_) < 0)
+        SENF_THROW_SYSTEM_EXCEPTION("timer_create()");
+
+    struct sigaction sa;
+    ::memset(&sa, 0, sizeof(sa));
+    sa.sa_sigaction = &watchdog;
+    sa.sa_flags = SA_SIGINFO;
+    if (sigaction(SIGURG, &sa, 0) < 0)
+        SENF_THROW_SYSTEM_EXCEPTION("sigaction()");
+
+    sigset_t mask;
+    sigemptyset(&mask);
+    sigaddset(&mask, SIGURG);
+    if (sigprocmask(SIG_UNBLOCK, &mask, 0) < 0)
+        SENF_THROW_SYSTEM_EXCEPTION("sigprocmask()");
+}
+
+prefix_ senf::scheduler::FIFORunner::~FIFORunner()
+{
+    timer_delete(watchdogId_);
+    signal(SIGURG, SIG_DFL);
+}
+
 // At the moment, the FIFORunner is not very efficient with many non-runnable tasks since the
 // complete list of tasks is traversed on each run().
 //
 // To optimize this, we woould need a way to find the relative ordering of two tasks in O(1) (at the
-// moment, this is an O)(N) operation by traversing the list).
+// moment, this is an O(N) operation by traversing the list).
 //
 // One idea is, to give each task an 'order' value. Whenever a task is added at the end, it's order
 // value is set to the order value of the last task + 1. Whenever the order value such added exceeds
@@ -85,10 +119,21 @@ prefix_ void senf::scheduler::FIFORunner::run()
     tasks_.push_back(null);
     TaskList::iterator end (TaskList::current(null));
     next_ = tasks_.begin();
+    struct itimerspec timer;
+    timer.it_interval.tv_sec = 0;
+    timer.it_interval.tv_nsec = 0;
+    timer.it_value.tv_sec = 1;
+    timer.it_value.tv_nsec = 0;
     while (next_ != end) {
         TaskInfo & task (*next_);
         if (task.runnable) {
             task.runnable = false;
+            if (timer_settime(watchdogId_, 0, &timer, 0) < 0)
+                SENF_THROW_SYSTEM_EXCEPTION("timer_settime()");
+            runningName_ = task.name;
+#       ifdef SENF_DEBUG
+            runningBacktrace_ = task.backtrace;
+#       endif
             TaskList::iterator i (next_);
             ++ next_;
             tasks_.splice(tasks_.end(), tasks_, i);
@@ -97,10 +142,27 @@ prefix_ void senf::scheduler::FIFORunner::run()
         else
             ++ next_;
     }
+    timer.it_value.tv_sec = 0;
+    if (timer_settime(watchdogId_, 0, &timer, 0) < 0)
+        SENF_THROW_SYSTEM_EXCEPTION("timer_settime()");
     tasks_.erase(end);
     next_ = tasks_.end();
 }
 
+prefix_ void senf::scheduler::FIFORunner::watchdog(int, siginfo_t * si, void *)
+{
+    FIFORunner & runner (*static_cast<FIFORunner *>(si->si_value.sival_ptr));
+    ++ runner.hangCount_;
+    write(1, "\n\n*** Scheduler task hanging: ", 30);
+    write(1, runner.runningName_.c_str(), runner.runningName_.size());
+    write(1, "\n", 1);
+#ifdef SENF_DEBUG
+    write(1, "Task was initialized at\n", 24);
+    write(1, runner.runningBacktrace_.c_str(), runner.runningBacktrace_.size());
+#endif
+    write(1, "\n", 1);
+}
+
 ///////////////////////////////cc.e////////////////////////////////////////
 #undef prefix_
 //#include "FIFORunner.mpp"
diff --git a/Scheduler/FIFORunner.cci b/Scheduler/FIFORunner.cci
index 5247d5d850e20bbe971c6676cf4cf2eb813bf8a1..1061f4dc8599aa0171d65c5e7d98468ca2edcdec 100644
--- a/Scheduler/FIFORunner.cci
+++ b/Scheduler/FIFORunner.cci
@@ -26,6 +26,10 @@
 //#include "FIFORunner.ih"
 
 // Custom includes
+#ifdef SENF_DEBUG
+#include <sstream>
+#include "../Utils/Backtrace.hh"
+#endif
 
 #define prefix_ inline
 ///////////////////////////////cci.p///////////////////////////////////////
@@ -37,13 +41,20 @@ prefix_ senf::scheduler::FIFORunner::TaskInfo::TaskInfo()
 prefix_ senf::scheduler::FIFORunner::TaskInfo::~TaskInfo()
 {}
 
-prefix_ senf::scheduler::FIFORunner::FIFORunner()
-    : tasks_ (), next_ (tasks_.end())
-{}
-
 prefix_ void senf::scheduler::FIFORunner::enqueue(TaskInfo * task)
 {
     tasks_.push_back(*task);
+#ifdef SENF_DEBUG
+    std::stringstream ss;
+    backtrace(ss, 32);
+    task->backtrace = ss.str();
+#endif
+}
+
+prefix_ unsigned senf::scheduler::FIFORunner::hangCount()
+    const
+{
+    return hangCount_;
 }
 
 ///////////////////////////////cci.e///////////////////////////////////////
diff --git a/Scheduler/FIFORunner.hh b/Scheduler/FIFORunner.hh
index 3ad8d7e1850380d33531951f5e5708698f0ebca8..9121445fecb097c6045c6eeb937ff3dbd910e2fe 100644
--- a/Scheduler/FIFORunner.hh
+++ b/Scheduler/FIFORunner.hh
@@ -27,6 +27,7 @@
 #define HH_FIFORunner_ 1
 
 // Custom includes
+#include <signal.h>
 #include <boost/utility.hpp>
 #include "../boost/intrusive/ilist.hpp"
 #include "../boost/intrusive/ilist_hook.hpp"
@@ -37,7 +38,14 @@
 namespace senf { 
 namespace scheduler {
 
-    /** \brief
+    /** \brief Task execution scheduler
+
+        The FIFORunner implements a simple FIFO scheduler for callback tasks. All tasks are held in
+        a queue. Whenever a task is run, it is moved to the end of the queue. Running the queue will
+        run all tasks which have been marked runnable. 
+
+        When running a task, it's runnable flag is always reset. The flag is set whenever an event
+        is posted for the task.
       */
     class FIFORunner
         : boost::noncopyable
@@ -55,14 +63,26 @@ namespace scheduler {
         ///////////////////////////////////////////////////////////////////////////
         // Types
 
+        /** \brief Task structure
+
+            TaskInfo is the base-class for all tasks.
+         */
         struct TaskInfo 
             : public TaskListBase
         {
             TaskInfo();
             virtual ~TaskInfo();
 
-            bool runnable;
-            virtual void run() = 0;
+            bool runnable;              ///< Runnable flag
+                                        /**< This must be set to \c true when the task is
+                                             runnable. It is reset automatically when the task is
+                                             run. */
+
+            std::string name;           ///< Descriptive task name
+#       ifdef SENF_DEBUG
+            std::string backtrace;
+#       endif
+            virtual void run() = 0;     ///< Called to run the task
         };
 
         ///////////////////////////////////////////////////////////////////////////
@@ -70,20 +90,35 @@ namespace scheduler {
         ///@{
 
         FIFORunner();
+        ~FIFORunner();
 
         ///@}
         ///////////////////////////////////////////////////////////////////////////
 
-        void enqueue(TaskInfo * task);
-        void dequeue(TaskInfo * task);
+        void enqueue(TaskInfo * task);  ///< Add task to queue
+        void dequeue(TaskInfo * task);  ///< Remove task from queue
         
-        void run();
+        void run();                     ///< Run queue
+
+        unsigned hangCount() const;     ///< Number of task expirations
+                                        /**< The FIFORunner manages a watchdog which checks, that a
+                                             single task does not run continuously for a longer time
+                                             or block. If a task runs for more than 1s, a warning is
+                                             printed  and the hangCount is increased. */
 
     protected:
 
     private:
+        static void watchdog(int, siginfo_t *, void *);
+
         TaskList tasks_;
         TaskList::iterator next_;
+        int watchdogId_;
+        std::string runningName_;
+#   ifdef SENF_DEBUG
+        std::string runningBacktrace_;
+#   endif
+        unsigned hangCount_;
     };
 
 
diff --git a/Scheduler/FdDispatcher.cc b/Scheduler/FdDispatcher.cc
index 7d033a3126092a15c82188fc89f9a5d618968e42..4103b510e84066ab5d58b42683186306335032fb 100644
--- a/Scheduler/FdDispatcher.cc
+++ b/Scheduler/FdDispatcher.cc
@@ -46,10 +46,11 @@ prefix_ senf::scheduler::FdDispatcher::~FdDispatcher()
     }
 }
 
-prefix_ void senf::scheduler::FdDispatcher::add(int fd, Callback const & cb, int events)
+prefix_ bool senf::scheduler::FdDispatcher::add(std::string const & name, int fd,
+                                                Callback const & cb, int events)
 {
     if (events == 0)
-        return;
+        return true;
     
     FdMap::iterator i (fds_.find(fd));
     if (i == fds_.end()) {
@@ -60,11 +61,28 @@ prefix_ void senf::scheduler::FdDispatcher::add(int fd, Callback const & cb, int
     }
     FdEvent & event (i->second);
 
-    if (events & EV_READ) event.FdEvent::ReadTask::cb = cb;
-    if (events & EV_PRIO) event.FdEvent::PrioTask::cb = cb;
-    if (events & EV_WRITE) event.FdEvent::WriteTask::cb = cb;
+    if (events & EV_READ) {
+        event.FdEvent::ReadTask::cb = cb;
+        event.FdEvent::ReadTask::name = name;
+    }
+    if (events & EV_PRIO) {
+        event.FdEvent::PrioTask::cb = cb;
+        event.FdEvent::PrioTask::name = name;
+    }
+    if (events & EV_WRITE) {
+        event.FdEvent::WriteTask::cb = cb;
+        event.FdEvent::WriteTask::name = name;
+    }
 
-    manager_.set(fd, event.activeEvents(), &event);
+    if (! manager_.set(fd, event.activeEvents(), &event)) {
+        runner_.dequeue(static_cast<FdEvent::ReadTask*>(&i->second));
+        runner_.dequeue(static_cast<FdEvent::PrioTask*>(&i->second));
+        runner_.dequeue(static_cast<FdEvent::WriteTask*>(&i->second));
+        fds_.erase(i);
+        return false;
+    }
+    else
+        return true;
 }
 
 prefix_ void senf::scheduler::FdDispatcher::remove(int fd, int events)
@@ -77,9 +95,18 @@ prefix_ void senf::scheduler::FdDispatcher::remove(int fd, int events)
         return;
     FdEvent & event (i->second);
 
-    if (events & EV_READ) event.FdEvent::ReadTask::cb = 0;
-    if (events & EV_PRIO) event.FdEvent::PrioTask::cb = 0;
-    if (events & EV_WRITE) event.FdEvent::WriteTask::cb = 0;
+    if (events & EV_READ) {
+        event.FdEvent::ReadTask::cb = 0;
+        event.FdEvent::ReadTask::name.clear();
+    }
+    if (events & EV_PRIO) {
+        event.FdEvent::PrioTask::cb = 0;
+        event.FdEvent::PrioTask::name.clear();
+    }
+    if (events & EV_WRITE) {
+        event.FdEvent::WriteTask::cb = 0;
+        event.FdEvent::WriteTask::name.clear();
+    }
 
     int activeEvents (event.activeEvents());
     if (! activeEvents) {
@@ -106,7 +133,7 @@ prefix_ void senf::scheduler::FdDispatcher::FdEvent::signal(int e)
     if (events & EV_WRITE)
         WriteTask::runnable = true;
 
-    if (events & (EV_ERR | EV_HUP) && ! events & (EV_READ | EV_PRIO | EV_WRITE)) {
+    if ((events & (EV_ERR | EV_HUP)) && ! (events & (EV_READ | EV_PRIO | EV_WRITE))) {
         if (ReadTask::cb) ReadTask::runnable = true;
         if (PrioTask::cb) PrioTask::runnable = true;
         if (WriteTask::cb) WriteTask::runnable = true;
diff --git a/Scheduler/FdDispatcher.cci b/Scheduler/FdDispatcher.cci
index 2222cee8cc0340dc86c90e9921f0c0ed483649b6..d7c1034eea6a5d2224062dd80226f5c7b3fa97eb 100644
--- a/Scheduler/FdDispatcher.cci
+++ b/Scheduler/FdDispatcher.cci
@@ -37,6 +37,12 @@ prefix_ senf::scheduler::FdDispatcher::FdDispatcher(FdManager & manager, FIFORun
     : manager_ (manager), runner_ (runner)
 {}
 
+prefix_ bool senf::scheduler::FdDispatcher::empty()
+    const
+{
+    return fds_.empty();
+}
+
 ///////////////////////////////////////////////////////////////////////////
 // senf::scheduler::FdDispatcher::FdEvent
 
diff --git a/Scheduler/FdDispatcher.hh b/Scheduler/FdDispatcher.hh
index 696be2a3f448a864bd3fe84c288ef0bd1be72d71..affc61da678d0eb348de76e138a6da6bae6977b7 100644
--- a/Scheduler/FdDispatcher.hh
+++ b/Scheduler/FdDispatcher.hh
@@ -38,7 +38,9 @@
 namespace senf {
 namespace scheduler {
 
-    /** \brief
+    /** \brief Scheduler dispatcher managing poll-able file descriptors
+
+        File descriptors are added directly to the event loop.
       */
     class FdDispatcher
     {
@@ -64,12 +66,27 @@ namespace scheduler {
         ///@}
         ///////////////////////////////////////////////////////////////////////////
 
-        void add(int fd, Callback const & cb, int events = EV_ALL);
-        void remove(int fd, int events = EV_ALL);
+        bool add(std::string const & name, int fd, Callback const & cb, int events = EV_ALL);
+                                        ///< Add file descriptor callback
+                                        /**< There is always one active callback for each
+                                             combination of file descriptor and event. Registering a
+                                             new callback will overwrite the old callback.
+                                             \param[in] name descriptive name
+                                             \param[in] fd file descriptor
+                                             \param[in] cb callback
+                                             \param[in] events Events to call \a cb for */
+
+        void remove(int fd, int events = EV_ALL); ///< Remove callback
+                                        /**< \param[in] fd file descriptor
+                                             \param[in] events Events for which to remove the
+                                                 callback */
+        
+        bool empty() const;             ///< \c true, if no file descriptors are registered.
 
     protected:
 
     private:
+        /// Internal: File descriptor event
         struct FdEvent 
             : public detail::FdTask<0, FdEvent>,
               public detail::FdTask<1, FdEvent>,
diff --git a/Scheduler/FdDispatcher.ih b/Scheduler/FdDispatcher.ih
index 81ea330223f5cf481ea5ebf52fee018a5c9f1f42..42d3c85ca969642769463802de01653822c8bb41 100644
--- a/Scheduler/FdDispatcher.ih
+++ b/Scheduler/FdDispatcher.ih
@@ -34,6 +34,11 @@ namespace senf {
 namespace scheduler {
 namespace detail {
     
+    /** \brief Internal: File descriptor task
+        
+        \implementation This class allows to inherit FIFORunner::TaskInfo multiple times to add
+            multiple tasks to one event and still allows efficient access to the event class
+     */
     template <unsigned index, class Self>
     struct FdTask
         : public FIFORunner::TaskInfo
diff --git a/Scheduler/FdDispatcher.test.cc b/Scheduler/FdDispatcher.test.cc
index 2a87e71660474e6bab4b5fbb0ed7aafa7cedea54..853d862e7e4af554368a67ca312295b06f728f51 100644
--- a/Scheduler/FdDispatcher.test.cc
+++ b/Scheduler/FdDispatcher.test.cc
@@ -185,8 +185,8 @@ BOOST_AUTO_UNIT_TEST(fdDispatcher)
         BOOST_FAIL("connect");
     }
 
-    SENF_CHECK_NO_THROW( dispatcher.add(sock, boost::bind(&callback, sock, _1),
-                                        senf::scheduler::FdDispatcher::EV_READ) );
+    BOOST_CHECK( dispatcher.add("testHandler", sock, boost::bind(&callback, sock, _1),
+                                senf::scheduler::FdDispatcher::EV_READ) );
     event = 0;
     SENF_CHECK_NO_THROW( manager.processOnce() );
     SENF_CHECK_NO_THROW( runner.run() );
@@ -197,8 +197,8 @@ BOOST_AUTO_UNIT_TEST(fdDispatcher)
 
     strcpy(buffer,"WRITE");
     size=5;
-    SENF_CHECK_NO_THROW( dispatcher.add(sock, boost::bind(&callback, sock, _1),
-                                        senf::scheduler::FdDispatcher::EV_WRITE) );
+    BOOST_CHECK( dispatcher.add("testHandler", sock, boost::bind(&callback, sock, _1),
+                                senf::scheduler::FdDispatcher::EV_WRITE) );
     event = 0;
     sleep(1);
     SENF_CHECK_NO_THROW( manager.processOnce() );
diff --git a/Scheduler/FdManager.cc b/Scheduler/FdManager.cc
index 323825d2d08ab95e50c42940bf985b89af876dc6..db17838b3a4233083eda99f7fadd0b8a4659ff57 100644
--- a/Scheduler/FdManager.cc
+++ b/Scheduler/FdManager.cc
@@ -35,6 +35,7 @@
 prefix_ void senf::scheduler::FdManager::processOnce()
 {
     Poller<Event>::range events (poller_.wait());
+    eventTime_ = ClockService::now();
     for (Poller<Event>::iterator i (events.begin()); i != events.end(); ++i)
         i->second->signal(i->first);
 }
diff --git a/Scheduler/FdManager.cci b/Scheduler/FdManager.cci
index 5f7c175ae24e5944601217e535f02df804887121..467a97a2d57617d1928dfa788075c3a8512819c9 100644
--- a/Scheduler/FdManager.cci
+++ b/Scheduler/FdManager.cci
@@ -33,9 +33,13 @@
 ///////////////////////////////////////////////////////////////////////////
 // senf::scheduler::FdManager
 
-prefix_ void senf::scheduler::FdManager::set(int fd, int events, Event * entry)
+prefix_ senf::scheduler::FdManager::FdManager()
+    : eventTime_ (senf::ClockService::now())
+{}
+
+prefix_ bool senf::scheduler::FdManager::set(int fd, int events, Event * entry)
 {
-    poller_.set(fd, events, entry);
+    return poller_.set(fd, events, entry);
 }
 
 prefix_ void senf::scheduler::FdManager::remove(int fd)
@@ -54,6 +58,12 @@ prefix_ int senf::scheduler::FdManager::timeout()
     return poller_.timeout();
 }
 
+prefix_ senf::ClockService::clock_type senf::scheduler::FdManager::eventTime()
+    const
+{
+    return eventTime_;
+}
+
 ///////////////////////////////////////////////////////////////////////////
 // senf::scheduler::FdManager::Event
 
diff --git a/Scheduler/FdManager.hh b/Scheduler/FdManager.hh
index ecc7f98f5e62c1ac00f1061f3537104df6169c2f..4d7b05e5f0be07cf6768cd19231af2825e693cb9 100644
--- a/Scheduler/FdManager.hh
+++ b/Scheduler/FdManager.hh
@@ -28,6 +28,7 @@
 
 // Custom includes
 #include "Poller.hh"
+#include "ClockService.hh"
 
 //#include "FdManager.mpp"
 ///////////////////////////////hh.p////////////////////////////////////////
@@ -35,7 +36,21 @@
 namespace senf {
 namespace scheduler {
 
-    /** \brief
+    /** \brief Manage file descriptor event processing
+
+        The FdManager is the internal class which manages all events (all events need to somehow be
+        made accessible via a file descriptor). File descriptors are added or removed from the
+        FdManager which then allows waiting until an event occurs on one of the descriptors.
+
+        Registered events must be derived from FdManager::Event. The FdManager does \e not manage
+        the event classes, it just manages pointers to externally owned events (the events are owned
+        by the respective dispatchers). 
+
+        When an event is posted, it's \c signal() member is called. However, this call will \e not
+        execute the user callback registered for the event, it will just mark the relevant tasks as
+        runnable.
+
+        \implementation
       */
     class FdManager
     {
@@ -43,9 +58,10 @@ namespace scheduler {
         ///////////////////////////////////////////////////////////////////////////
         // Types
 
+        ///< Event baseclass
         struct Event {
             virtual ~Event();
-            virtual void signal(int events) = 0;
+            virtual void signal(int events) = 0; ///< Called when the given event is posted
         };
 
         enum Events { 
@@ -57,21 +73,41 @@ namespace scheduler {
         ///\name Structors and default members
         ///@{
 
+        FdManager();
+
         ///@}
         ///////////////////////////////////////////////////////////////////////////
 
-        void set(int fd, int events, Event * entry);
-        void remove(int fd);
-
-        void timeout(int t);
-        int timeout() const;
-
-        void processOnce();
+        bool set(int fd, int events, Event * entry); ///< Set file descriptor event mask
+                                        /**< This sets the event mask for \a fd to \a events which
+                                             is a combination of values from the \c Events enum. If
+                                             \a fd is already registered, the registration is
+                                             changed to conform to the parameters passed, otherwise
+                                             a new registration is added.
+                                             \param[in] fd file descriptor
+                                             \param[in] events events to register for
+                                             \param[in] entry event to signal 
+                                             \returns \c true, if \a fd supports polling, \c false
+                                                 otherwise */
+        void remove(int fd);            ///< Remove \a fd from the manager
+
+        void timeout(int t);            ///< Set event timeout
+                                        /**< proceseOnce() will wait for max \a t milliseconds for
+                                             an event to occur. If set to -1, processOnce() will
+                                             wait forever. */
+        int timeout() const;            ///< Get  timeout in milliseconds
+
+        void processOnce();             ///< Wait for events
+                                        /**< This call waits until at least one event is posted but
+                                             no longer than the current timeout(). */
+
+        ClockService::clock_type eventTime() const; ///< Time of last event
 
     protected:
 
     private:
         Poller<Event> poller_;
+        senf::ClockService::clock_type eventTime_;
     };
 
 }}
diff --git a/Scheduler/FileDispatcher.cc b/Scheduler/FileDispatcher.cc
index 1989c90f969f2604b0ac6b52c893a9a299a94d8e..780335cbd165b200230424621986b40982abced1 100644
--- a/Scheduler/FileDispatcher.cc
+++ b/Scheduler/FileDispatcher.cc
@@ -47,7 +47,8 @@ prefix_ senf::scheduler::FileDispatcher::~FileDispatcher()
     }
 }
 
-prefix_ void senf::scheduler::FileDispatcher::add(int fd, Callback const & cb, int events)
+prefix_ void senf::scheduler::FileDispatcher::add(std::string const & name, int fd,
+                                                  Callback const & cb, int events)
 {
     if (events == 0)
         return;
@@ -60,8 +61,14 @@ prefix_ void senf::scheduler::FileDispatcher::add(int fd, Callback const & cb, i
     }
     FileEvent & event (i->second);
 
-    if (events & EV_READ) event.FileEvent::ReadTask::cb = cb;
-    if (events & EV_WRITE) event.FileEvent::WriteTask::cb = cb;
+    if (events & EV_READ) {
+        event.FileEvent::ReadTask::cb = cb;
+        event.FileEvent::ReadTask::name = name;
+    }
+    if (events & EV_WRITE) {
+        event.FileEvent::WriteTask::cb = cb;
+        event.FileEvent::WriteTask::name = name;
+    }
     
     manager_.timeout(0);
 }
diff --git a/Scheduler/FileDispatcher.cci b/Scheduler/FileDispatcher.cci
index 7d932d11da99cca52dbb72b2187a2aedc75620b4..a18ea27971bcaa360f4f95f1d861b750871f0e3a 100644
--- a/Scheduler/FileDispatcher.cci
+++ b/Scheduler/FileDispatcher.cci
@@ -51,6 +51,12 @@ prefix_ int senf::scheduler::FileDispatcher::timeout()
     return managerTimeout_;
 }
 
+prefix_ bool senf::scheduler::FileDispatcher::empty()
+    const
+{
+    return files_.empty();
+}
+
 ///////////////////////////////cci.e///////////////////////////////////////
 #undef prefix_
 
diff --git a/Scheduler/FileDispatcher.hh b/Scheduler/FileDispatcher.hh
index cd4b884117d825ec542e8893e1e5936dd92acbe4..4bff54db8b8e13f2bc4714e8d17781556dbc8396 100644
--- a/Scheduler/FileDispatcher.hh
+++ b/Scheduler/FileDispatcher.hh
@@ -38,7 +38,14 @@
 namespace senf {
 namespace scheduler {
 
-    /** \brief
+    /** \brief Scheduler dispatcher managing disc files
+
+        This dispatcher manages file descriptors which are connected to disc files. Since disc files
+        do not support select() / poll() / epoll(), they are considered to be always ready (which is
+        especially untrue for remote files e.g. vie NFS).
+
+        The FileDispatcher will change the FdManager's event timeout value to 0 (from -1) whenever
+        there is at least one file registered.
       */
     class FileDispatcher
     {
@@ -64,17 +71,37 @@ namespace scheduler {
         ///@}
         ///////////////////////////////////////////////////////////////////////////
         
-        void add(int fd, Callback const & cb, int events = EV_ALL);
+        void add(std::string const & name, int fd, Callback const & cb, int events = EV_ALL);
+                                        ///< Add file descriptor callback
+                                        /**< There is always one active callback for each
+                                             combination of file descriptor and event. Registering a
+                                             new callback will overwrite the old callback.
+                                             \param[in] name descriptive name
+                                             \param[in] fd file descriptor
+                                             \param[in] cb callback
+                                             \param[in] events Events to call \a cb for */
+
         void remove(int fd, int events = EV_ALL);
+                                        /**< \param[in] fd file descriptor
+                                             \param[in] events Events for which to remove the
+                                                 callback */
+
+        void prepareRun();              ///< Prepare tasks
+                                        /**< This must be called after the FdManager returns before
+                                             running the runnable tasks. */
 
-        void prepareRun();
+        void timeout(int t);            ///< Change FdManager timeout
+                                        /**< Since the FileDispatcher must be able to change the
+                                             timeout value, the value must be set here and not
+                                             directly in the FdManager. */
+        int timeout() const;            ///< Retrieve current timeout value
 
-        void timeout(int t);
-        int timeout() const;
+        bool empty() const;             ///< \c true, if no files are registered.
 
     protected:
 
     private:
+        /// Internal: Disk file event
         struct FileEvent
             : public detail::FdTask<0, FileEvent>,
               public detail::FdTask<1, FileEvent>
diff --git a/Scheduler/FileDispatcher.test.cc b/Scheduler/FileDispatcher.test.cc
index 045f125d3895f8c2ddce7b38e30baf99eaf89055..f923616200877292c7795383ae5883fb5a78267d 100644
--- a/Scheduler/FileDispatcher.test.cc
+++ b/Scheduler/FileDispatcher.test.cc
@@ -66,7 +66,8 @@ BOOST_AUTO_UNIT_TEST(fileDispatcher)
     int fd (open("/dev/null", O_RDWR));
     
     senf::ClockService::clock_type t (senf::ClockService::now());
-    SENF_CHECK_NO_THROW( dispatcher.add(fd, &handler, senf::scheduler::FileDispatcher::EV_READ) );
+    SENF_CHECK_NO_THROW( dispatcher.add("testHandler", fd, &handler, 
+                                        senf::scheduler::FileDispatcher::EV_READ) );
     SENF_CHECK_NO_THROW( manager.processOnce() );
     SENF_CHECK_NO_THROW( dispatcher.prepareRun() );
     SENF_CHECK_NO_THROW( runner.run() );
diff --git a/Scheduler/Mainpage.dox b/Scheduler/Mainpage.dox
index e2d5f5423ef29c0ff489d2a5dcaaec45465ae1d6..40f3f0e7e0eaea44961158562fa93c641e79e8e8 100644
--- a/Scheduler/Mainpage.dox
+++ b/Scheduler/Mainpage.dox
@@ -20,27 +20,112 @@
 // Free Software Foundation, Inc.,
 // 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
-namespace senf {
-
 /** \mainpage The SENF Scheduler Library
 
-    The Scheduler library provides a simple yet flexible abstraction of the standard asynchronous
-    UNIX mainloop utilizing \c select or \c poll. The Scheduler library is based on the highly
-    efficient (but linux specific) \c epoll() system call.
+    The %Scheduler Library provides a single-threaded application event-loop multiplexing multiple
+    event sources.
+
+    \autotoc
 
-    The library provides
-    \li the ClockService as a reliable high-resolution highly accurate monotonous time source
-    \li a central \ref Scheduler %singleton and
-    \li \ref ReadHelper and \ref WriteHelper templates to simplify common tasks.
+    \section scheduler_scheduler The Scheduler
 
-    The Scheduler supports several types of scheduling activites:
-    \li Arbitrary file descriptors (however, local disk file-handles are not guaranteed
-        non-blocking)
+    The main interface is the senf::Scheduler class. This provides support for several types of
+    events:
+    \li File descriptors
     \li Timers
-    \li UNIX Signals
+    \li UNIX signals
+
+    \see senf::Scheduler
+
+
+    \section scheduler_clockservice The ClockService
+
+    To support precise event timing, the senf::ClockService class implements a reliable monotonous
+    time source. It is based on the high precision POSIX clock and adds support for reliable
+    conversion between an abstract clock type and absolute date/time
+
+    \see senf::ClockService
+
+
+    \section scheduler_helpers Miscellaneous helpers
+
+    To ease the use of the Scheduler there are some additional helpers managing callbacks and
+    registrations.
+
+    \li senf::ReadHelper reads data from an arbitrary file descritor until a use specified condition
+        is met (e.g. number of chars read or a specific character sequence is found in the input).
+    \li senf::WriteHelper writes data to an arbitrary file descriptor until all provided data has
+        been written.
+    \li senf::SchedulerBinding is an RAII class which manages the registration of a file descriptor
+        with the %scheduler.
+    \li senf::SchedulerTimer is an RAII class which manages a timer registration.
+
+    
+    \section scheduler_i Implementation
+
+    senf::Scheduler is only a wrapper around the real implementation. The real implementation is now
+    based on a modular dispatcher architecture
+
+    \see \ref scheduler_implementation
  */
 
-}
+/** \page scheduler_implementation The Scheduler Implementation
+
+    The implentation architecture now is based on a set of dispatchers, one for each type of
+    event.
+
+    \autotoc
+
+    \section scheduler_i_overview Overview
+
+    The %scheduler utilizes the following components
+
+    \li There is a dispatcher for each event type. This dispatcher manages the event specific
+        registration and unregistration. The dispatcher is owns the event (and task) objects.
+    
+    \li Every registered event is represented by an event specific event class instance.
+
+    \li The Dispatcher ultimately registeres with the senf::scheduler::FdManager. Since the
+        event-loop is based on epoll() (it could easily be changed to be based on select() or
+        poll()), all events must ultimately be represented by some type of file descriptor (not
+        necessarily a \e different file descriptor for each event).
+
+    \li The Dispatcher registeres all callbacks as tasks with the runner
+        (senf::scheduler::FIFORunner).
+
+    \li The senf::scheduler::FdManager uses senf::scheduler::Poller to access the low-level epoll()
+    API.
+
+    All these classes are \e not singletons. They are all instantiatied by the senf::Scheduler
+    singleton.
+
+
+    \section scheduler_i_dispatchers Dispatchers
+    
+    There is one dispatcher for each event type
+
+    \li senf::scheduler::FdDispatcher manages poll-able file descriptors. This does \e not include
+        real files.
+    \li senf::scheduler::FileDispatcher manages disk files
+    \li senf::scheduler::TimerDispatcher manages timers
+    \li senf::scheduler::SignalDispatcher manages UNIX signals
+
+    At the moment, each dispatcher has a specific API and the integration into the main-loop is not
+    standardized for performance reasons.
+
+    The Dispatcher owns all relevant data, the other classese (senf::scheduler::FIFORunner,
+    senf::scheduler::FdManager) only hold pointers to the data owned by the dispatcher.
+
+    
+    \section scheduler_i_mainloop The main loop
+
+    The application mainloop is part of senf::Scheduler. It is constructed by calling the correct
+    members of all these classes repeatedly in the correct order: 
+    \li First dispatchers are set up
+    \li then the senf::scheduler::FdManager is called to wait for an event
+    \li After cleaning up the dispatchers,
+    \li the senf::scheduler::FIFORunner is called to executed all now runnable tasks.
+ */
 
 
 // Local Variables:
@@ -51,4 +136,5 @@ namespace senf {
 // ispell-local-dictionary: "american"
 // mode: flyspell
 // mode: auto-fill
+// compile-command: "scons -U doc"
 // End:
diff --git a/Scheduler/Poller.hh b/Scheduler/Poller.hh
index 0dc5504aa4c95fdf6ab955756b24bfc91efa30a4..0bedf72dbd09445b9ea2c729842597af2489fcd9 100644
--- a/Scheduler/Poller.hh
+++ b/Scheduler/Poller.hh
@@ -38,7 +38,13 @@
 namespace senf {
 namespace scheduler {
 
-    /** \brief
+    /** \brief Epoll abstraction
+
+        This class provides a more convenient interface to the epoll() API. File descriptors are
+        registered with pointers to a parameterized event type. After waiting for an event, the
+        Poller allows to iterate over the event instances for all posted events.
+
+        \tparam Value Event type
       */
     template <class Value>
     class Poller
@@ -75,12 +81,17 @@ namespace scheduler {
         ///@}
         ///////////////////////////////////////////////////////////////////////////
 
-        bool set(int fd, int events, Value * data);
-        void remove(int fd);
-        range wait();
+        bool set(int fd, int events, Value * data); ///< Set file descriptor event data and mask
+                                        /**< The Poller does \e not own \a data. The value is owned
+                                             by some external entity (the dispatcher to be more
+                                             precise). */
+        void remove(int fd);            ///< Remove file descriptor
+        range wait();                   ///< Wait for one event
+                                        /**< \returns a range of iterators which iterate over the
+                                             data values registered with the event */
         
-        void timeout(int t);
-        int timeout() const;
+        void timeout(int t);            ///< Set event timeout to \a t milliseconds
+        int timeout() const;            ///< Current event timeout
 
     private:
         int epollFd_;
diff --git a/Scheduler/ReadHelper.ct b/Scheduler/ReadHelper.ct
index 981d9705cdc0ea3fd9f4593e57647258bf860fad..42d068add8674825ef4ba97190001194dfafdef3 100644
--- a/Scheduler/ReadHelper.ct
+++ b/Scheduler/ReadHelper.ct
@@ -57,8 +57,7 @@ prefix_ void senf::ReadHelper<Handle>::revoke()
 
 template <class Handle>
 prefix_ void
-senf::ReadHelper<Handle>::dispatchProcess(ptr helper, Handle handle,
-                                                 senf::Scheduler::EventId event)
+senf::ReadHelper<Handle>::dispatchProcess(ptr helper, Handle handle, int event)
 {
     // since we have a 'ptr' argument, the instance cannot be deleted
     // before this method returns
@@ -66,8 +65,7 @@ senf::ReadHelper<Handle>::dispatchProcess(ptr helper, Handle handle,
 }
 
 template <class Handle>
-prefix_ void senf::ReadHelper<Handle>::process(Handle handle,
-                                                      senf::Scheduler::EventId event)
+prefix_ void senf::ReadHelper<Handle>::process(Handle handle,int event)
 {
     try {
         if (event != senf::Scheduler::EV_READ)
diff --git a/Scheduler/ReadHelper.hh b/Scheduler/ReadHelper.hh
index 34246e2fa6fe1dd5c6f12a2b5b5f3b7133eebc04..d43afd72689d4cad65b4b3beadb4fe36131fa042 100644
--- a/Scheduler/ReadHelper.hh
+++ b/Scheduler/ReadHelper.hh
@@ -131,8 +131,8 @@ namespace senf {
 
         ReadHelper(Handle handle, unsigned maxSize,  InternalPredicate * predicate, Callback cb);
 
-        static void dispatchProcess(ptr helper, Handle handle, senf::Scheduler::EventId event);
-        void process(Handle handle, senf::Scheduler::EventId event);
+        static void dispatchProcess(ptr helper, Handle handle, int event);
+        void process(Handle handle, int event);
         void done();
 
         Handle handle_;
diff --git a/Scheduler/Scheduler.cc b/Scheduler/Scheduler.cc
index 3d61946a8fdae0f6c6b68bbbb895e71d29a96b16..02364a42760922ddcb068d1598ca1f6896de32e7 100644
--- a/Scheduler/Scheduler.cc
+++ b/Scheduler/Scheduler.cc
@@ -31,310 +31,27 @@
     threads)
  */
 
-// Here a basic concept of how to add signal support to the scheduler:
-//
-// ... no, I had overlooked one race condition. So back to the signal-pipe approach ...
-
 #include "Scheduler.hh"
 //#include "Scheduler.ih"
 
 // Custom includes
-#include "../Utils/senfassert.hh"
-#include <errno.h>
-#include <sys/epoll.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include "../Utils/Exception.hh"
-#include "../Utils/Backtrace.hh"
-
-static const int EPollInitialSize = 16;
 
 #define prefix_
 ///////////////////////////////cc.p////////////////////////////////////////
 
-prefix_ senf::Scheduler::Scheduler()
-    : files_(0), timerIdCounter_(0), epollFd_ (epoll_create(EPollInitialSize)), terminate_(false),
-      eventTime_(0), eventEarly_(ClockService::milliseconds(11)), eventAdjust_(0)
-{
-    if (epollFd_<0)
-        SENF_THROW_SYSTEM_EXCEPTION("::epoll_create()");
-
-    if (::pipe(sigpipe_) < 0)
-        SENF_THROW_SYSTEM_EXCEPTION("::pipe()");
-
-    int flags (::fcntl(sigpipe_[1],F_GETFL));
-    if (flags < 0) 
-        SENF_THROW_SYSTEM_EXCEPTION("::fcntl(F_GETFL)");
-    flags |= O_NONBLOCK;
-    if (::fcntl(sigpipe_[1], F_SETFL, flags) < 0) 
-        SENF_THROW_SYSTEM_EXCEPTION("::fcntl(F_SETFL)");
-
-    ::epoll_event ev;
-    ::memset(&ev, 0, sizeof(ev));
-    ev.events = EV_READ;
-    ev.data.fd = sigpipe_[0];
-    if (::epoll_ctl(epollFd_, EPOLL_CTL_ADD, sigpipe_[0], &ev) < 0)
-        SENF_THROW_SYSTEM_EXCEPTION("::epoll_ctl(EPOLL_CTL_ADD)");
-}
-
-prefix_ void senf::Scheduler::registerSignal(unsigned signal, SimpleCallback const & cb)
-{
-    ::sigset_t sig;
-    ::sigemptyset(&sig);
-    if (::sigaddset(&sig, signal) < 0)
-        throw InvalidSignalNumberException();
-    ::sigprocmask(SIG_BLOCK, &sig, 0);
-    ::sigaddset(&sigset_, signal);
-    if (sigHandlers_.size() <= signal)
-        sigHandlers_.resize(signal+1);
-    sigHandlers_[signal] = cb;
-
-    registerSigHandlers();
-}
-
-prefix_ void senf::Scheduler::unregisterSignal(unsigned signal)
-{
-    if (::sigdelset(&sigset_, signal) < 0)
-        throw InvalidSignalNumberException();
-    sigHandlers_[signal] = 0;
-    ::signal(signal, SIG_DFL);
-    registerSigHandlers();
-}
-
-prefix_ void senf::Scheduler::do_add(int fd, FdCallback const & cb, int eventMask)
-{
-    if (eventMask == 0)
-        return;
-
-    FdTable::iterator i (fdTable_.find(fd));
-    int action (EPOLL_CTL_MOD);
-    if (i == fdTable_.end()) {
-        action = EPOLL_CTL_ADD;
-        i = fdTable_.insert(std::make_pair(fd, EventSpec())).first;
-    }
-    else if (i->second.epollMask() == 0) {
-        action = EPOLL_CTL_ADD;
-        fdErase_.erase( std::remove(fdErase_.begin(), fdErase_.end(), unsigned(fd)),
-                        fdErase_.end() );
-    }
-
-    if (eventMask & EV_READ)  i->second.cb_read = cb;
-    if (eventMask & EV_PRIO)  i->second.cb_prio = cb;
-    if (eventMask & EV_WRITE) i->second.cb_write = cb;
-
-    epoll_event ev;
-    memset(&ev,0,sizeof(ev));
-    ev.events = i->second.epollMask();
-    ev.data.fd = fd;
-
-    for (;;) {
-        if ( (!i->second.file) && (epoll_ctl(epollFd_, action, fd, &ev) < 0) ) {
-            switch (errno) {
-            case EPERM :
-                // Argh ... epoll does not support ordinary files :-( :-(
-                i->second.file = true;
-                ++ files_;
-                return;
-            case ENOENT :
-                action = EPOLL_CTL_ADD;
-                break;
-            default:
-                SENF_THROW_SYSTEM_EXCEPTION("::epoll_ctl()");
-            }
-        }
-        else
-            return;
-    }
-}
-
-prefix_ void senf::Scheduler::do_remove(int fd, int eventMask)
-{
-    if (eventMask == 0)
-        return;
-
-    FdTable::iterator i (fdTable_.find(fd));
-    if (i == fdTable_.end())
-        return;
-
-    if (eventMask & EV_READ)  i->second.cb_read = 0;
-    if (eventMask & EV_PRIO)  i->second.cb_prio = 0;
-    if (eventMask & EV_WRITE) i->second.cb_write = 0;
-
-    epoll_event ev;
-    memset(&ev,0,sizeof(ev));
-    ev.events = i->second.epollMask();
-    ev.data.fd = fd;
-
-    int action (EPOLL_CTL_MOD);
-    bool file (i->second.file);
-    if (ev.events==0) {
-        action = EPOLL_CTL_DEL;
-        fdErase_.push_back(fd);
-    }
-
-    if (! file && epoll_ctl(epollFd_, action, fd, &ev) < 0 && errno != ENOENT)
-        SENF_THROW_SYSTEM_EXCEPTION("::epoll_ctl()");
-    if (file)
-        -- files_;
-}
-
-prefix_ void senf::Scheduler::registerSigHandlers()
-{
-    for (unsigned signal (1); signal < sigHandlers_.size(); ++signal) {
-        if (sigHandlers_[signal]) {
-            struct ::sigaction sa;
-            sa.sa_sigaction = & Scheduler::sigHandler;
-            sa.sa_mask = sigset_;
-            sa.sa_flags = SA_SIGINFO;
-            if (signal == SIGCHLD)
-                sa.sa_flags |= SA_NOCLDSTOP;
-            if (::sigaction(signal, &sa, 0) < 0)
-                SENF_THROW_SYSTEM_EXCEPTION("::sigaction()");
-        }
-    }
-}
-
-prefix_ void senf::Scheduler::sigHandler(int signal, ::siginfo_t * siginfo, void *)
-{
-    // This is a bit unsafe. Better write single bytes and place the siginfo into an explicit
-    // queue. Since signals are only unblocked during epoll_wait, we even wouldn't need to
-    // synchronize access to that queue any further.
-
-    ::write(instance().sigpipe_[1], siginfo, sizeof(*siginfo));
-
-    // We ignore errors. The file handle is set to non-blocking IO. If any failure occurs (pipe
-    // full), the signal will be dropped. That's like kernel signal handling which may also drop
-    // signals.
-}
-
-prefix_ int senf::Scheduler::EventSpec::epollMask()
-    const
-{
-    int mask (0);
-    if (cb_read)  mask |= EPOLLIN;
-    if (cb_prio)  mask |= EPOLLPRI;
-    if (cb_write) mask |= EPOLLOUT;
-    return mask;
-}
-
 prefix_ void senf::Scheduler::process()
 {
     terminate_ = false;
-    eventTime_ = ClockService::now();
-    while (! terminate_) {
-
-        // Since a callback may have disabled further timers, we need to check for canceled timeouts
-        // again.
-
-        while (! timerQueue_.empty()) {
-            TimerMap::iterator i (timerQueue_.top());
-            if (! i->second.canceled)
-                break;
-            timerMap_.erase(i);
-            timerQueue_.pop();
-        }
-
-        for (FdEraseList::iterator i (fdErase_.begin()); i != fdErase_.end(); ++i) 
-            fdTable_.erase(*i);
-        fdErase_.clear();
-
-        int timeout (-1);
-        if (files_ > 0)
-            timeout = 0;
-        else {
-            if (timerQueue_.empty()) {
-                if (fdTable_.empty())
-                    break;
-            }
-            else {
-                ClockService::clock_type delta (
-                    (timerQueue_.top()->second.timeout - eventTime_ + eventAdjust_)/1000000UL);
-                timeout = delta < 0 ? 0 : delta;
-            }
-        }
-
-        ///\todo Handle more than one epoll_event per call
-        struct epoll_event ev;
-        
-        if (::sigprocmask(SIG_UNBLOCK, &sigset_, 0) < 0)
-            SENF_THROW_SYSTEM_EXCEPTION("::sigprocmask(SIG_UNBLOCK)");
-        int events (::epoll_wait(epollFd_, &ev, 1, timeout));
-        if (::sigprocmask(SIG_BLOCK, &sigset_, 0) < 0)
-            SENF_THROW_SYSTEM_EXCEPTION("::sigprocmask(SIG_BLOCK)");
-
-        if (events<0)
-            if (errno != EINTR)
-                SENF_THROW_SYSTEM_EXCEPTION("::epoll_wait()");
-
-        eventTime_ = ClockService::now();
-
-        // We always run timeout handlers. This is important, even if a file-descriptor is signaled
-        // since some descriptors (e.g. real files) will *always* be ready and we still may want to
-        // handle timers.  Time handlers are run before file events to not delay them unnecessarily.
-
-        while (! timerQueue_.empty()) {
-            TimerMap::iterator i (timerQueue_.top());
-            if (i->second.canceled)
-                ;
-            else if (i->second.timeout <= eventTime_ + eventEarly_)
-                i->second.cb();
-            else
-                break;
-            timerQueue_.pop();
-            timerMap_.erase(i);
-        }
-
-        // Check the signal queue
-        if (events > 0 && ev.data.fd == sigpipe_[0]) {
-            ::siginfo_t siginfo;
-            if (::read(sigpipe_[0], &siginfo, sizeof(siginfo)) < int(sizeof(siginfo))) {
-                // We ignore truncated records which may only occur if the signal
-                // queue became filled up
-                SENF_LOG((senf::log::IMPORTANT)("Truncated signal record!"));
-                continue;
-            }
-            if (siginfo.si_signo < int(sigHandlers_.size()) && sigHandlers_[siginfo.si_signo])
-                sigHandlers_[siginfo.si_signo]();
-            continue;
-        }
-
-        for (FdTable::iterator i = fdTable_.begin(); i != fdTable_.end(); ++i) {
-            EventSpec & spec (i->second);
-
-            if (! (spec.file || (events > 0 && i->first == ev.data.fd)))
-                continue;
-                
-            unsigned extraFlags (0);
-            unsigned mask (spec.file ? spec.epollMask() : ev.events);
-
-            if (mask & EPOLLHUP) extraFlags |= EV_HUP;
-            if (mask & EPOLLERR) extraFlags |= EV_ERR;
-
-            if (mask & EPOLLIN) {
-                SENF_ASSERT(spec.cb_read);
-                spec.cb_read(EventId(EV_READ | extraFlags));
-            }
-            else if (mask & EPOLLPRI) {
-                SENF_ASSERT(spec.cb_prio);
-                spec.cb_prio(EventId(EV_PRIO | extraFlags));
-            }
-            else if (mask & EPOLLOUT) {
-                SENF_ASSERT(spec.cb_write);
-                spec.cb_write(EventId(EV_WRITE | extraFlags));
-            }
-            else {
-                // This branch is only taken, if HUP or ERR is signaled but none of IN/OUT/PRI. 
-                // In this case we will signal all registered callbacks. The callbacks must be
-                // prepared to be called multiple times if they are registered to more than
-                // one event.
-                if (spec.cb_write) 
-                    spec.cb_write(EventId(extraFlags));
-                if (spec.cb_prio) 
-                    spec.cb_prio(EventId(extraFlags));
-                if (spec.cb_read) 
-                    spec.cb_read(EventId(extraFlags));
-            }
-        }
+    while(! terminate_ && ! (fdDispatcher_.empty() &&
+                             timerDispatcher_.empty() &&
+                             fileDispatcher_.empty())) {
+        signalDispatcher_.unblockSignals();
+        timerDispatcher_.unblockSignals();
+        manager_.processOnce();
+        timerDispatcher_.blockSignals();
+        signalDispatcher_.blockSignals();
+        fileDispatcher_.prepareRun();
+        runner_.run();
     }
 }
 
diff --git a/Scheduler/Scheduler.cci b/Scheduler/Scheduler.cci
index f436274e54bb4f3d72a188958b5da3c1c9e10916..f8a565eb0c82b7b65757f40ab3775075067aaca5 100644
--- a/Scheduler/Scheduler.cci
+++ b/Scheduler/Scheduler.cci
@@ -27,54 +27,100 @@
 //#include "Scheduler.ih"
 
 // Custom includes
+#include <boost/format.hpp>
 
 #define prefix_ inline
 ///////////////////////////////cci.p///////////////////////////////////////
 
+// private members
+
+prefix_ void senf::Scheduler::do_add(int fd, FdCallback const & cb, int eventMask)
+{
+    do_add((boost::format("<anon fd %d>") % fd).str(), fd, cb, eventMask);
+}
+
+prefix_ void senf::Scheduler::do_add(std::string const & name, int fd, FdCallback const & cb,
+                                     int eventMask)
+{
+    if (! fdDispatcher_.add(name, fd, cb, eventMask))
+        fileDispatcher_.add(name, fd, cb, eventMask);
+}
+
+prefix_ void senf::Scheduler::do_remove(int fd, int eventMask)
+{
+    // We don't know, where the descriptor is registered. However, this is no problem since removing
+    // a non-registered fd is a no-opp
+    fdDispatcher_.remove(fd, eventMask);
+    fileDispatcher_.remove(fd, eventMask);
+}
+
+// public members
+
 prefix_ senf::Scheduler::Scheduler & senf::Scheduler::instance()
 {
     static Scheduler instance;
     return instance;
 }
 
-prefix_ unsigned senf::Scheduler::timeout(ClockService::clock_type timeout,
-                                          SimpleCallback const & cb)
+prefix_ int senf::retrieve_filehandle(int fd)
+{
+    return fd;
+}
+
+prefix_ senf::Scheduler::timer_id senf::Scheduler::timeout(ClockService::clock_type timeout,
+                                                           SimpleCallback const & cb)
+{
+    return timerDispatcher_.add("<anon timer>", timeout, cb);
+}
+
+prefix_ senf::Scheduler::timer_id senf::Scheduler::timeout(std::string const & name,
+                                                           ClockService::clock_type timeout,
+                                                           SimpleCallback const & cb)
 {
-    ++ timerIdCounter_;
-    TimerMap::iterator i (
-        timerMap_.insert(std::make_pair(timerIdCounter_, 
-                                        TimerSpec(timeout,cb,timerIdCounter_))).first);
-    timerQueue_.push(i);
-    return timerIdCounter_;
+    return timerDispatcher_.add(name, timeout, cb);
 }
 
-prefix_ void senf::Scheduler::cancelTimeout(unsigned id)
+prefix_ void senf::Scheduler::cancelTimeout(timer_id id)
 {
-    TimerMap::iterator i (timerMap_.find(id));
-    if (i != timerMap_.end())
-        i->second.canceled = true;
+    timerDispatcher_.remove(id);
 }
 
 prefix_ senf::ClockService::clock_type senf::Scheduler::timeoutEarly()
     const
 {
-    return eventEarly_;
+    SENF_LOG( (senf::log::IMPORTANT) 
+              ("timeoutEarly() is deprecated and a no-op. It will be removed") );
+    return 0;
 }
 
 prefix_ void senf::Scheduler::timeoutEarly(ClockService::clock_type v)
 {
-    eventEarly_ = v;
+    SENF_LOG( (senf::log::IMPORTANT) 
+              ("timeoutEarly() is deprecated and a no-op. It will be removed") );
 }
 
 prefix_ senf::ClockService::clock_type senf::Scheduler::timeoutAdjust()
     const
 {
-    return eventAdjust_;
+    SENF_LOG( (senf::log::IMPORTANT) 
+              ("timeoutAdjust() is deprecated and a no-op. It will be removed") );
+    return 0;
 }
 
 prefix_ void senf::Scheduler::timeoutAdjust(ClockService::clock_type v)
 {
-    eventAdjust_ = v;
+    SENF_LOG( (senf::log::IMPORTANT) 
+              ("timeoutAdjust() is deprecated and a no-op. It will be removed") );
+}
+
+prefix_ void senf::Scheduler::registerSignal(unsigned signal, SignalCallback const & cb)
+{
+    signalDispatcher_.add(signal, cb);
+}
+
+prefix_ void senf::Scheduler::unregisterSignal(unsigned signal)
+{
+    signalDispatcher_.remove(signal);
 }
 
 prefix_ void senf::Scheduler::terminate()
@@ -85,19 +131,22 @@ prefix_ void senf::Scheduler::terminate()
 prefix_ senf::ClockService::clock_type senf::Scheduler::eventTime()
     const
 {
-    return eventTime_;
+    return manager_.eventTime();
 }
 
-prefix_ int senf::retrieve_filehandle(int fd)
+prefix_ unsigned senf::Scheduler::hangCount()
+    const
 {
-    return fd;
+    return runner_.hangCount();
 }
 
-prefix_ senf::Scheduler::TimerSpecCompare::result_type
-senf::Scheduler::TimerSpecCompare::operator()(first_argument_type a, second_argument_type b)
-{
-    return a->second < b->second;
-}
+prefix_ senf::Scheduler::Scheduler()
+    : terminate_ (false), 
+      fdDispatcher_ (manager_, runner_),
+      timerDispatcher_ (manager_, runner_),
+      signalDispatcher_ (manager_, runner_),
+      fileDispatcher_ (manager_, runner_)
+{}
 
 ///////////////////////////////cci.e///////////////////////////////////////
 #undef prefix_
diff --git a/Scheduler/Scheduler.cti b/Scheduler/Scheduler.cti
index 1404615f900beb7a8bc746fe5d43d57541d6a532..aff6271732af3790a72cb98d849b131fdb643be8 100644
--- a/Scheduler/Scheduler.cti
+++ b/Scheduler/Scheduler.cti
@@ -39,6 +39,13 @@ prefix_ void senf::Scheduler::add(Handle const & handle, FdCallback const & cb,
     do_add(retrieve_filehandle(handle),cb,eventMask);
 }
 
+template <class Handle>
+prefix_ void senf::Scheduler::add(std::string const & name, Handle const & handle,
+                                  FdCallback const & cb, int eventMask)
+{
+    do_add(name, retrieve_filehandle(handle),cb,eventMask);
+}
+
 template <class Handle>
 prefix_ void senf::Scheduler::remove(Handle const & handle, int eventMask)
 {
diff --git a/Scheduler/Scheduler.hh b/Scheduler/Scheduler.hh
index 695e9b393203242977aa5c048a34b269c34f9f1b..89e9d2386f974cf107509face7fec3dac7ea6c82 100644
--- a/Scheduler/Scheduler.hh
+++ b/Scheduler/Scheduler.hh
@@ -28,14 +28,11 @@
 #define HH_Scheduler_ 1
 
 // Custom includes
-#include <signal.h>
-#include <map>
-#include <queue>
-#include <boost/function.hpp>
-#include <boost/utility.hpp>
-#include <boost/call_traits.hpp>
-#include <boost/integer.hpp>
-#include "ClockService.hh"
+#include "../Utils/Logger/SenfLog.hh"
+#include "FdDispatcher.hh"
+#include "TimerDispatcher.hh"
+#include "SignalDispatcher.hh"
+#include "FileDispatcher.hh"
 #include "../Utils/Logger/SenfLog.hh"
 
 //#include "scheduler.mpp"
@@ -44,10 +41,10 @@
 /** \brief SENF Project namespace */
 namespace senf {
 
-    /** \brief Singleton class to manage the event loop
+    /** \brief Visible scheduler interface
 
-        The %scheduler singleton manages the central event loop. It manages and dispatches all types
-        of events managed by the scheduler library:
+        The %scheduler singleton manages access to the %scheduler library. It provides access to
+        several event dispatchers:
         \li File descriptor notifications
         \li Timeouts
         \li UNIX Signals
@@ -87,7 +84,10 @@ namespace senf {
         // e.g. in Foo::Foo() constructor:
         Scheduler::instance().add(handle_, senf::membind(&Foo::callback, this)), EV_READ)
         \endcode
-        
+
+        The handler can also be identified by an arbitrary, user specified name. This name is used
+        in error messages to identify the failing handler.
+
 
         \section sched_fd Registering file descriptors
         
@@ -125,20 +125,9 @@ namespace senf {
         Scheduler::instance().cancelTimeout(id);
         \endcode 
         Timing is based on the ClockService, which provides a high resolution and strictly
-        monotonous time source. Registering a timeout will fire the callback when the target time is
-        reached. The timer may be canceled by passing the returned \a id to cancelTimeout().
-
-        There are two parameters which adjust the exact: \a timeoutEarly and \a timeoutAdjust. \a
-        timeoutEarly is the time, a callback may be called before the deadline time is
-        reached. Setting this value below the scheduling granularity of the kernel will have the
-        %scheduler go into a <em>busy wait</em> (that is, an endless loop consuming 100% of CPU
-        recources) until the deadline time is reached! This is seldom desired. The default setting
-        of 11ms is adequate in most cases (it's slightly above the lowest linux scheduling
-        granularity). 
-
-        The other timeout scheduling parameter is \a timeoutAdjust. This value will be added to the
-        timeout value before calculating the next delay value thereby compensating for \a
-        timeoutEarly. By default, this value is set to 0 but may be changed if needed.
+        monotonous time source which again is based on POSIX timers. Registering a timeout will fire
+        the callback when the target time is reached. The timer may be canceled by passing the
+        returned \a id to cancelTimeout().
 
 
         \section sched_signals Registering POSIX/UNIX signals
@@ -155,13 +144,10 @@ namespace senf {
         A registered signal does \e not count as 'something to do'. It is therefore not possible to
         wait for signals \e only.
 
-        \todo Fix EventId parameter (probably to int) to allow |-ing without casting ...
-        
+        \todo Change the Scheduler API to use RAII. Additionally, this will remove all dynamic
+            memory allocations from the scheduler.
         \todo Fix the file support to use threads (?) fork (?) and a pipe so it works reliably even
             over e.g. NFS.
-
-        \todo Add a check in the alarm callback which is already called every x seconds to check,
-            that a single callback is not blocking.
       */
     class Scheduler
         : boost::noncopyable
@@ -181,35 +167,31 @@ namespace senf {
             \li Error flags. These additional flags may be passed to a handler to pass an error
                 condition to the handler. 
          */
-        enum EventId { 
-            EV_NONE  =  0   /**< No event */
-          , EV_READ  =  1   /**< File descriptor is readable */
-          , EV_PRIO  =  2   /**< File descriptor has OOB data */
-          , EV_WRITE =  4   /**< File descriptor is writable */
-          , EV_ALL   =  7   /**< Used to register all events at once (read/prio/write) */
-          , EV_HUP   =  8   /**< Hangup condition on file handle */
-          , EV_ERR   = 16   /**< Error condition on file handle */
+        enum EventId {
+            EV_NONE  = 0                              /**< No event */
+          , EV_READ  = scheduler::FdManager::EV_READ  /**< File descriptor is readable */
+          , EV_PRIO  = scheduler::FdManager::EV_PRIO  /**< File descriptor has OOB data */
+          , EV_WRITE = scheduler::FdManager::EV_WRITE /**< File descriptor is writable */
+          , EV_ALL   = scheduler::FdManager::EV_READ
+                     | scheduler::FdManager::EV_PRIO
+                     | scheduler::FdManager::EV_WRITE /**< Used to register all events at once
+                                                           (read/prio/write) */
+          , EV_HUP   = scheduler::FdManager::EV_HUP   /**< Hangup condition on file handle */
+          , EV_ERR   = scheduler::FdManager::EV_ERR   /**< Error condition on file handle */
         };
 
-        /** \brief Template typedef for Callback type
-
-            This is a template typedef (which does not exist in C++) that is, a template class whose
-            sole member is a typedef symbol defining the callback type given the handle type.
-
-            The Callback is any callable object taking a \c Handle and an \c EventId as argument.
-            \code
-            template <class Handle>
-            struct GenericCallback {
-                typedef boost::function<void (typename boost::call_traits<Handle>::param_type,
-                                              EventId) > Callback;
-            };
-            \endcode
-         */
-        typedef boost::function<void (EventId)> FdCallback;
+        /** \brief Callback type for file descriptor events */
+        typedef boost::function<void (int)> FdCallback;
 
         /** \brief Callback type for timer events */
         typedef boost::function<void ()> SimpleCallback;
 
+        /** \brief Callback type for signal events */
+        typedef boost::function<void (siginfo_t const &)> SignalCallback;
+
+        /** \brief Timer id type */
+        typedef scheduler::TimerDispatcher::timer_id timer_id;
+
         ///////////////////////////////////////////////////////////////////////////
         ///\name Structors and default members
         ///@{
@@ -225,11 +207,6 @@ namespace senf {
             This static member is used to access the singleton instance. This member is save to
             return a correctly initialized %scheduler instance even if called at global construction
             time
-
-            \implementation This static member just defines the %scheduler as a static method
-                variable. The C++ standard then provides above guarantee. The instance will be
-                initialized the first time, the code flow passes the variable declaration found in
-                the instance() body.
          */
         static Scheduler & instance();
 
@@ -240,20 +217,29 @@ namespace senf {
         ///\{
 
         template <class Handle>
-        void add(Handle const & handle, FdCallback const & cb,
-                 int eventMask = EV_ALL); ///< Add file handle event callback
+        void add(std::string const & name, Handle const & handle, FdCallback const & cb,
+                 int eventMask = EV_ALL);  ///< Add file handle event callback
                                         /**< add() will add a callback to the %scheduler. The
                                              callback will be called for the given type of event on
                                              the given  arbitrary file-descriptor or
                                              handle-like object. If there already is a Callback
                                              registered for one of the events requested, the new
                                              handler will replace the old one.
+                                             \param[in] name descriptive name to identify the
+                                                 callback.
                                              \param[in] handle file descriptor or handle providing
                                                  the Handle interface defined above.
                                              \param[in] cb callback
                                              \param[in] eventMask arbitrary combination via '|'
                                                  operator of \ref senf::Scheduler::EventId "EventId"
                                                  designators. */
+ 
+        template <class Handle>        
+        void add(Handle const & handle, FdCallback const & cb,
+                 int eventMask = EV_ALL); ///< Add file handle event callback
+                                        /**< \see add() */
+
+
         template <class Handle>
         void remove(Handle const & handle, int eventMask = EV_ALL); ///< Remove event callback
                                         /**< remove() will remove any callback registered for any of
@@ -264,36 +250,42 @@ namespace senf {
                                              \param[in] eventMask arbitrary combination via '|'
                                                  operator of \ref senf::Scheduler::EventId "EventId"
                                                  designators. */
+
         ///\}
 
         ///\name Timeouts
         ///\{
 
-        unsigned timeout(ClockService::clock_type timeout, SimpleCallback const & cb); 
+        timer_id timeout(std::string const & name, ClockService::clock_type timeout, 
+                         SimpleCallback const & cb); 
                                         ///< Add timeout event
                                         /**< \returns timer id
+                                             \param[in] name descriptive name to identify the
+                                                 callback.
                                              \param[in] timeout timeout in nanoseconds
                                              \param[in] cb callback to call after \a timeout
                                                  milliseconds */
 
-        void cancelTimeout(unsigned id); ///< Cancel timeout \a id
+        timer_id timeout(ClockService::clock_type timeout, SimpleCallback const & cb); 
+                                        ///< Add timeout event
+                                        /**< \see timeout() */
+
+        void cancelTimeout(timer_id id); ///< Cancel timeout \a id
 
+#ifndef DOXYGEN
         ClockService::clock_type timeoutEarly() const;
-                                        ///< Fetch the \a timeoutEarly parameter
         void timeoutEarly(ClockService::clock_type v);
-                                        ///< Set the \a timeoutEarly parameter
 
         ClockService::clock_type timeoutAdjust() const;
-                                        ///< Fetch the \a timeoutAdjust parameter
         void timeoutAdjust(ClockService::clock_type v);
-                                        ///< Set the \a timeoutAdjust parameter
+#endif
 
         ///\}
 
         ///\name Signal handlers
         ///\{
         
-        void registerSignal(unsigned signal, SimpleCallback const & cb);
+        void registerSignal(unsigned signal, SignalCallback const & cb);
                                         ///< Add signal handler
                                         /**< \param[in] signal signal number to register handler for
                                              \param[in] cb callback to call whenever \a signal is
@@ -302,12 +294,6 @@ namespace senf {
         void unregisterSignal(unsigned signal);
                                         ///< Remove signal handler for \a signal
 
-        /// The signal number passed to registerSignal or unregisterSignal is invalid
-        struct InvalidSignalNumberException : public senf::Exception
-        { InvalidSignalNumberException() 
-              : senf::Exception("senf::Scheduler::InvalidSignalNumberException"){} };
-
-
         ///\}
 
         void process();                 ///< Event handler main loop
@@ -328,92 +314,26 @@ namespace senf {
                                              delivered \e not the time it should have been delivered
                                              (in the case of timers). */
 
+        unsigned hangCount() const;
+
     protected:
 
     private:
         Scheduler();
 
         void do_add(int fd, FdCallback const & cb, int eventMask = EV_ALL);
-        void do_remove(int fd, int eventMask = EV_ALL);
-
-        void registerSigHandlers();
-        static void sigHandler(int signal, ::siginfo_t * siginfo, void *);
-
-#       ifndef DOXYGEN
-
-        /** \brief Descriptor event specification
-            \internal */
-        struct EventSpec
-        {
-            FdCallback cb_read;
-            FdCallback cb_prio;
-            FdCallback cb_write;
-
-            EventSpec() : file(false) {}
-
-            int epollMask() const;
-
-            bool file;
-        };
-
-        /** \brief Timer event specification
-            \internal */
-        struct TimerSpec
-        {
-            TimerSpec() : timeout(), cb() {}
-            TimerSpec(ClockService::clock_type timeout_, SimpleCallback cb_, unsigned id_)
-                : timeout(timeout_), cb(cb_), id(id_), canceled(false) {}
-
-            bool operator< (TimerSpec const & other) const
-                { return timeout > other.timeout; }
-
-            ClockService::clock_type timeout;
-            SimpleCallback cb;
-            unsigned id;
-            bool canceled;
-        };
+        void do_add(std::string const & name, int fd, FdCallback const & cb, 
+                    int eventMask = EV_ALL);
+        void do_remove(int fd, int eventMask);
 
-#       endif 
-
-        typedef std::map<int,EventSpec> FdTable;
-        typedef std::map<unsigned,TimerSpec> TimerMap; // sorted by id
-        typedef std::vector<unsigned> FdEraseList;
-
-#       ifndef DOXYGEN
-
-        struct TimerSpecCompare
-        {
-            typedef TimerMap::iterator first_argument_type;
-            typedef TimerMap::iterator second_argument_type;
-            typedef bool result_type;
-            
-            result_type operator()(first_argument_type a, second_argument_type b);
-        };
-
-#       endif
-
-        typedef std::priority_queue<TimerMap::iterator, std::vector<TimerMap::iterator>, 
-                                    TimerSpecCompare> TimerQueue; // sorted by time
-
-        typedef std::vector<SimpleCallback> SigHandlers;
-
-        FdTable fdTable_;
-        FdEraseList fdErase_;
-        unsigned files_;
-
-        unsigned timerIdCounter_;
-        TimerQueue timerQueue_;
-        TimerMap timerMap_;
-
-        SigHandlers sigHandlers_;
-        ::sigset_t sigset_;
-        int sigpipe_[2];
-
-        int epollFd_;
         bool terminate_;
-        ClockService::clock_type eventTime_;
-        ClockService::clock_type eventEarly_;
-        ClockService::clock_type eventAdjust_;
+        scheduler::FdManager manager_;
+        scheduler::FIFORunner runner_;
+
+        scheduler::FdDispatcher fdDispatcher_;
+        scheduler::TimerDispatcher timerDispatcher_;
+        scheduler::SignalDispatcher signalDispatcher_;
+        scheduler::FileDispatcher fileDispatcher_;
     };
 
     /** \brief Default file descriptor accessor
diff --git a/Scheduler/Scheduler.test.cc b/Scheduler/Scheduler.test.cc
index 5da6b8c47e5b01d130c9b6dff4f7fb315623ae76..0501762eeb925e45523907497db8069e76c292ee 100644
--- a/Scheduler/Scheduler.test.cc
+++ b/Scheduler/Scheduler.test.cc
@@ -141,7 +141,7 @@ namespace {
     int size;
     int event;
 
-    void callback(int fd, Scheduler::EventId ev)
+    void callback(int fd, int ev)
     {
         event = ev;
         switch (event & Scheduler::EV_ALL) {
@@ -160,8 +160,10 @@ namespace {
         Scheduler::instance().terminate();
     }
 
+    bool timeoutCalled = false;
     void timeout()
     {
+        timeoutCalled = true;
         Scheduler::instance().terminate();
     }
 
@@ -177,7 +179,7 @@ namespace {
         return handle.fd_;
     }
 
-    void handleCallback(HandleWrapper const & handle, Scheduler::EventId event)
+    void handleCallback(HandleWrapper const & handle, int event)
     {
         if (handle.tag_ != "TheTag")
             return;
@@ -191,12 +193,12 @@ namespace {
     
     ClockService::clock_type sigtime (0);
 
-    void sigusr()
+    void sigusr(siginfo_t const &)
     {
         sigtime = ClockService::now();
         Scheduler::instance().terminate();
     }
-        
+
     void delay(unsigned long milliseconds)
     {
         struct timespec ts;
@@ -204,9 +206,16 @@ namespace {
         ts.tv_nsec = (milliseconds % 1000) * 1000000;
         while (nanosleep(&ts,&ts) < 0 && errno == EINTR) ;
     }
+
+    void blockingHandler()
+    {
+        delay(1200);
+        Scheduler::instance().terminate();
+    }
+
 }
 
-BOOST_AUTO_UNIT_TEST(scheduler)
+BOOST_AUTO_UNIT_TEST(testScheduler)
 {
     int pid = start_server();
     BOOST_REQUIRE (pid);
@@ -239,15 +248,26 @@ BOOST_AUTO_UNIT_TEST(scheduler)
     buffer[size]=0;
     BOOST_CHECK_EQUAL( buffer, "READ" );
 
+    event = Scheduler::EV_NONE;
     BOOST_CHECK_NO_THROW( Scheduler::instance().timeout(
                               ClockService::now()+ClockService::milliseconds(200),&timeout) );
     BOOST_CHECK_NO_THROW( Scheduler::instance().timeout(
                               ClockService::now()+ClockService::milliseconds(400),&timeout) );
     ClockService::clock_type t (ClockService::now());
     BOOST_CHECK_NO_THROW( Scheduler::instance().process() );
-    BOOST_CHECK_PREDICATE( is_close, (ClockService::now()) (t+ClockService::milliseconds(200)) );
+    BOOST_CHECK_PREDICATE( is_close, (ClockService::now()-t) (ClockService::milliseconds(200)) );
+    BOOST_CHECK( timeoutCalled );
+    BOOST_CHECK_EQUAL( event, Scheduler::EV_NONE );
+    BOOST_CHECK_PREDICATE( is_close, (ClockService::now()) (Scheduler::instance().eventTime()) );
+    timeoutCalled = false;
+    BOOST_CHECK_NO_THROW( Scheduler::instance().process() );
+    BOOST_CHECK_PREDICATE( is_close, (ClockService::now()-t) (ClockService::milliseconds(400)) );
+    BOOST_CHECK( timeoutCalled );
+    BOOST_CHECK_EQUAL( event, Scheduler::EV_NONE );
+
+    BOOST_CHECK_NO_THROW( Scheduler::instance().timeout(ClockService::now(), &blockingHandler) );
     BOOST_CHECK_NO_THROW( Scheduler::instance().process() );
-    BOOST_CHECK_PREDICATE( is_close, (ClockService::now()) (t+ClockService::milliseconds(400)) );
+    BOOST_CHECK_EQUAL( Scheduler::instance().hangCount(), 1u );
 
     HandleWrapper handle(sock,"TheTag");
     BOOST_CHECK_NO_THROW( Scheduler::instance().add(handle,
diff --git a/Scheduler/SignalDispatcher.cc b/Scheduler/SignalDispatcher.cc
index 490c2c2715dcb648ff48e43190314d37db76d420..69d72bc815d4cfe5e8eeba4dbc7807341ddd5949 100644
--- a/Scheduler/SignalDispatcher.cc
+++ b/Scheduler/SignalDispatcher.cc
@@ -68,7 +68,7 @@ prefix_ void senf::scheduler::SignalDispatcher::add(int signal, Callback const &
         return;
     }
 
-    i = handlers_.insert(std::make_pair(signal, SignalEvent(cb))).first;
+    i = handlers_.insert(std::make_pair(signal, SignalEvent(signal, cb))).first;
     sigaddset(&sigSet_, signal);
     runner_.enqueue(&i->second);
 
diff --git a/Scheduler/SignalDispatcher.cci b/Scheduler/SignalDispatcher.cci
index 088fc92d02c2e373a0f12af263f3c59123a567d7..84fe9ab5f9b1c54bcf4df5895c8b40e8627822df 100644
--- a/Scheduler/SignalDispatcher.cci
+++ b/Scheduler/SignalDispatcher.cci
@@ -27,6 +27,7 @@
 
 // Custom includes
 #include <unistd.h>
+#include "../Utils/signalnames.hh"
 
 #define prefix_ inline
 ///////////////////////////////cci.p///////////////////////////////////////
@@ -45,12 +46,20 @@ prefix_ void senf::scheduler::SignalDispatcher::unblockSignals()
     blocked_ = false;
 }
 
+prefix_ bool senf::scheduler::SignalDispatcher::empty()
+    const
+{
+    return handlers_.empty();
+}
+
 ///////////////////////////////////////////////////////////////////////////
 // senf::scheduler::SignalDispatcher::SignalEvent
 
-prefix_ senf::scheduler::SignalDispatcher::SignalEvent::SignalEvent(Callback cb_)
+prefix_ senf::scheduler::SignalDispatcher::SignalEvent::SignalEvent(int signal, Callback cb_)
     : cb (cb_)
-{}
+{
+    name = signalName(signal);
+}
 
 prefix_ void senf::scheduler::SignalDispatcher::SignalEvent::run()
 {
diff --git a/Scheduler/SignalDispatcher.hh b/Scheduler/SignalDispatcher.hh
index b2c44a4dd2b7740862605c70e6eda172291c83c9..2c2b7ae56c412f7e26c99587fcc9ff4f23910a9f 100644
--- a/Scheduler/SignalDispatcher.hh
+++ b/Scheduler/SignalDispatcher.hh
@@ -38,7 +38,16 @@
 namespace senf {
 namespace scheduler {
 
-    /** \brief
+    /** \brief Scheduler dispatcher managing UNIX signals
+
+        This dispatcher supports registering UNIX signals with the Scheduler.
+
+        \implementation SignalDispatcher provides a single signal handler which all registered
+            signals are assigned to. When a signal is received, data is written to a pipe which has
+            been added to the FdManager and this signals the event.
+
+        \todo Add signal block/unblock management to the FdManager to reduce the number of
+            setprocmask() calls
       */
     class SignalDispatcher
         : public FdManager::Event
@@ -59,19 +68,27 @@ namespace scheduler {
         ///@}
         ///////////////////////////////////////////////////////////////////////////
 
-        void add(int signal, Callback const & cb);
-        void remove(int signal);
+        void add(int signal, Callback const & cb); ///< Add signal event
+                                        /**< \param[in] signal signal number
+                                             \param[in] cb Callback */
+
+        void remove(int signal); ///< Unregister signal event
+
+        void unblockSignals();          ///< Unblock registered signals
+                                        /**< Must be called before waiting for an event */
+        void blockSignals();            ///< Block registered signals
+                                        /**< Must be called directly after FdManager returns */
 
-        void blockSignals();
-        void unblockSignals();
+        bool empty() const;             ///< \c true, if no signal is registered.
 
     protected:
 
     private:
+        ///< Internal: UNIX signal event
         struct SignalEvent
             : public FIFORunner::TaskInfo
         {
-            explicit SignalEvent(Callback cb_);
+            SignalEvent(int signal, Callback cb_);
             virtual void run();
 
             siginfo_t siginfo;
diff --git a/Scheduler/SignalDispatcher.test.cc b/Scheduler/SignalDispatcher.test.cc
index d0bd0daec9da1aa1051f9402ad8ee8a527c1c174..7531aae456a01c0b1e253f986a2e0792c405b976 100644
--- a/Scheduler/SignalDispatcher.test.cc
+++ b/Scheduler/SignalDispatcher.test.cc
@@ -45,6 +45,10 @@ namespace {
 
 }
 
+#if 0
+// We can't test this when testing the Scheduler since the Scheduler instance
+// already uses the only SignalDispatcher instance allowed ...
+
 BOOST_AUTO_UNIT_TEST(signalDispatcher)
 {
     senf::scheduler::FdManager manager;
@@ -65,6 +69,8 @@ BOOST_AUTO_UNIT_TEST(signalDispatcher)
     SENF_CHECK_NO_THROW( dispatcher.remove(SIGUSR1) );
 }
 
+#endif
+
 ///////////////////////////////cc.e////////////////////////////////////////
 #undef prefix_
 
diff --git a/Scheduler/TimerDispatcher.cc b/Scheduler/TimerDispatcher.cc
index 225e608103d9221294babb495d7334632dc64118..520500d6e4d4763255ba804f21ba8e4c2e12f248 100644
--- a/Scheduler/TimerDispatcher.cc
+++ b/Scheduler/TimerDispatcher.cc
@@ -56,6 +56,7 @@ prefix_ senf::scheduler::TimerDispatcher::TimerDispatcher(FdManager & manager,
     }
 
     struct sigevent ev;
+    ::memset(&ev, 0, sizeof(ev));
     ev.sigev_notify = SIGEV_SIGNAL;
     ev.sigev_signo = SIGALRM;
     ev.sigev_value.sival_ptr = this;
@@ -84,10 +85,12 @@ prefix_ senf::scheduler::TimerDispatcher::~TimerDispatcher()
 }
 
 prefix_ senf::scheduler::TimerDispatcher::timer_id
-senf::scheduler::TimerDispatcher::add(ClockService::clock_type timeout, Callback const & cb)
+senf::scheduler::TimerDispatcher::add(std::string const & name,
+                                      ClockService::clock_type timeout, Callback const & cb)
 {
     while (timerIdIndex_.find(++lastId_) != timerIdIndex_.end()) ;
-    TimerMap::iterator i (timers_.insert(std::make_pair(timeout, TimerEvent(lastId_, cb, *this))));
+    TimerMap::iterator i (
+        timers_.insert(std::make_pair(timeout, TimerEvent(lastId_, cb, *this, name))));
     timerIdIndex_.insert(std::make_pair(lastId_, i));
     runner_.enqueue(&(i->second));
     if (! blocked_)
@@ -132,7 +135,7 @@ prefix_ void senf::scheduler::TimerDispatcher::signal(int events)
 
     TimerMap::iterator i (timers_.begin());
     TimerMap::iterator const i_end (timers_.end());
-    ClockService::clock_type now (ClockService::now());
+    ClockService::clock_type now (manager_.eventTime());
     for (; i != i_end && i->first <= now ; ++i)
         i->second.runnable = true;
 }
@@ -152,22 +155,41 @@ prefix_ void senf::scheduler::TimerDispatcher::sigHandler(int signal, ::siginfo_
 prefix_ void senf::scheduler::TimerDispatcher::reschedule()
 {
     struct itimerspec timer;
+    memset(&timer, 0, sizeof(timer));
     timer.it_interval.tv_sec = 0;
     timer.it_interval.tv_nsec = 0;
     if (timers_.empty()) {
+        SENF_LOG( (senf::log::VERBOSE)("Timer disabled") );
         timer.it_value.tv_sec = 0;
         timer.it_value.tv_nsec = 0;
     }
     else {
         ClockService::clock_type next (timers_.begin()->first);
+        if (next <= 0)
+            next = 1;
         timer.it_value.tv_sec = ClockService::in_seconds(next);
         timer.it_value.tv_nsec = ClockService::in_nanoseconds(
             next - ClockService::seconds(timer.it_value.tv_sec));
+        SENF_LOG( (senf::log::VERBOSE)("Next timeout scheduled @" << timer.it_value.tv_sec << "." 
+                   << std::setw(9) << std::setfill('0') << timer.it_value.tv_nsec) );
     }
     if (timer_settime(timerId_, TIMER_ABSTIME, &timer, 0)<0)
         SENF_THROW_SYSTEM_EXCEPTION("timer_settime()");
 }
 
+///////////////////////////////////////////////////////////////////////////
+// senf::scheduler::TimerDispatcher::TimerEvent
+
+prefix_ void senf::scheduler::TimerDispatcher::TimerEvent::run()
+{
+    Callback savedCb (cb);
+    dispatcher.remove(id);
+    // The member is now running WITHOUT AN OBJECT ... that has been destroyed above !!!!!!  On the
+    // other hand, if we do things the other way round, we have no idea, whether the callback might
+    // explicitly remove us and we have the same problem then ...
+    savedCb();
+}
+
 ///////////////////////////////cc.e////////////////////////////////////////
 #undef prefix_
 //#include "TimerDispatcher.mpp"
diff --git a/Scheduler/TimerDispatcher.cci b/Scheduler/TimerDispatcher.cci
index d0a330813828675f6934c4b45644afcb4a146ab1..6e8e9e6c0d76973af5903ba9a4044409f152e5ac 100644
--- a/Scheduler/TimerDispatcher.cci
+++ b/Scheduler/TimerDispatcher.cci
@@ -33,14 +33,17 @@
 
 prefix_ senf::scheduler::TimerDispatcher::TimerEvent::TimerEvent(timer_id id_,
                                                                  Callback const & cb_,
-                                                                 TimerDispatcher & dispatcher_)
+                                                                 TimerDispatcher & dispatcher_,
+                                                                 std::string const & n)
     : id (id_), cb (cb_), dispatcher (dispatcher_)
-{}
+{
+    name = n;    
+}
 
-prefix_ void senf::scheduler::TimerDispatcher::TimerEvent::run()
+prefix_ bool senf::scheduler::TimerDispatcher::empty()
+    const
 {
-    cb();
-    dispatcher.remove(id);
+    return timers_.empty();
 }
 
 ///////////////////////////////cci.e///////////////////////////////////////
diff --git a/Scheduler/TimerDispatcher.hh b/Scheduler/TimerDispatcher.hh
index 1a90ed5ba892e5d54b32e21b785b08c6f6ea2284..7b6f92a7712025e01e44e8fc0b539554f8b4396d 100644
--- a/Scheduler/TimerDispatcher.hh
+++ b/Scheduler/TimerDispatcher.hh
@@ -33,6 +33,7 @@
 #include "ClockService.hh"
 #include "FdManager.hh"
 #include "FIFORunner.hh"
+#include "../Utils/Logger/SenfLog.hh"
 
 //#include "TimerDispatcher.mpp"
 ///////////////////////////////hh.p////////////////////////////////////////
@@ -40,11 +41,20 @@
 namespace senf {
 namespace scheduler {
 
-    /** \brief
+    /** \brief Scheduler dispatcher managing timers
+
+        Timers are implemented using high-precision POSIX real-time timers. As such, the timer
+        granularity is given by clock_getres(CLOCK_MONOTONIC) which is 1ns on current linux kernels.
+
+        \implementation TimerDispatcher manages a single POSIX timer which is always programmed to
+            expire when the next scheduled timer needs to fire. The timer sends a signal (SIGALRM is
+            used). The handler writes data into a pipe which is has been added to the FdManager.
       */
     class TimerDispatcher
         : public FdManager::Event
     {
+        SENF_LOG_CLASS_AREA();
+
     public:
         ///////////////////////////////////////////////////////////////////////////
         // Types
@@ -62,19 +72,35 @@ namespace scheduler {
         ///@}
         ///////////////////////////////////////////////////////////////////////////
 
-        timer_id add(ClockService::clock_type timeout, Callback const & cb);
-        void remove(timer_id id);
-
-        void blockSignals();
-        void unblockSignals();
+        timer_id add(std::string const & name, ClockService::clock_type timeout, 
+                     Callback const & cb);
+                                        ///< Add timer event
+                                        /**< This call adds a new timer expiring at the given point
+                                             in time.
+                                             \param[in] name descriptive name
+                                             \param[in] timeout point in time when the timer is to
+                                                 expire 
+                                             \param[in] cb callback 
+                                             \returns a \c timer_id which can be used to remove the
+                                                 timer. */
+        void remove(timer_id id);       ///< Remove timer
+
+        void unblockSignals();          ///< Unblock internal signals
+                                        /**< Must be called before waiting for an event */
+        void blockSignals();            ///< Block internal signals
+                                        /**< Must be called directly after the FdManager returns */
+        
+        bool empty() const;             ///< \c true, if no timer is registered.
 
     protected:
 
     private:
+        /// Internal: Timer event
         struct TimerEvent
             : public FIFORunner::TaskInfo
         {
-            TimerEvent(timer_id id_, Callback const & cb_, TimerDispatcher & dispatcher_);
+            TimerEvent(timer_id id_, Callback const & cb_, TimerDispatcher & dispatcher_,
+                       std::string const & name);
             virtual void run();
 
             timer_id id;
diff --git a/Scheduler/TimerDispatcher.test.cc b/Scheduler/TimerDispatcher.test.cc
index 46e9a82aaaa2985c78620b561d5b3432998b996e..9f0599c607f0df9bc8796b513273ae495b81855d 100644
--- a/Scheduler/TimerDispatcher.test.cc
+++ b/Scheduler/TimerDispatcher.test.cc
@@ -60,16 +60,26 @@ BOOST_AUTO_UNIT_TEST(timerDispatcher)
     senf::ClockService::clock_type t (senf::ClockService::now());
     senf::scheduler::TimerDispatcher::timer_id id;
     SENF_CHECK_NO_THROW(
-        id = dispatcher.add( t + senf::ClockService::milliseconds(500), &handler ) );
+        id = dispatcher.add( "testTimer", t + senf::ClockService::milliseconds(500), &handler ) );
     SENF_CHECK_NO_THROW( dispatcher.unblockSignals() );
     SENF_CHECK_NO_THROW( manager.processOnce() );
     SENF_CHECK_NO_THROW( dispatcher.blockSignals() );
     SENF_CHECK_NO_THROW( runner.run() );
     senf::ClockService::clock_type t2 (senf::ClockService::now());
     BOOST_CHECK( called );
-    BOOST_CHECK_PREDICATE( is_close, (t2)(t + senf::ClockService::milliseconds(500)) );
+    BOOST_CHECK_PREDICATE( is_close, (t2-t)(senf::ClockService::milliseconds(500)) );
 
     SENF_CHECK_NO_THROW( dispatcher.remove(id) );
+
+    called=false;
+    t = senf::ClockService::now();
+    SENF_CHECK_NO_THROW( dispatcher.add( "testTimer", t, &handler ) );
+    SENF_CHECK_NO_THROW( dispatcher.unblockSignals() );
+    SENF_CHECK_NO_THROW( manager.processOnce() );
+    SENF_CHECK_NO_THROW( dispatcher.blockSignals() );
+    SENF_CHECK_NO_THROW( runner.run() );
+    BOOST_CHECK_PREDICATE( is_close, (t) (senf::ClockService::now()) );
+    BOOST_CHECK( called );
 }
 
 ///////////////////////////////cc.e////////////////////////////////////////
diff --git a/Utils/Daemon/Daemon.cc b/Utils/Daemon/Daemon.cc
index 94d95ea5a4e476a66991dd900c1b8c4d29525e44..708facadfdd1b475f47bf8967007a8edb142fe89 100644
--- a/Utils/Daemon/Daemon.cc
+++ b/Utils/Daemon/Daemon.cc
@@ -43,6 +43,7 @@
 #include "../Exception.hh"
 #include "../membind.hh"
 #include "../Backtrace.hh"
+#include "../signalnames.hh"
 
 // #define __USE_GNU
 #include <ucontext.h>
@@ -487,19 +488,9 @@ prefix_ bool senf::Daemon::pidfileCreate()
 namespace {
     void fatalSignalsHandler(int sig, ::siginfo_t * info, void * arg)
     {
-        static char const * const signames[] = {
-            "", 
-            "SIGHUP", "SIGINT", "SIGQUIT", "SIGILL", "SIGTRAP", "SIGABRT", "SIGBUS", "SIGFPE", 
-            "SIGKILL", "SIGUSR1", "SIGSEGV", "SIGUSR2", "SIGPIPE", "SIGALRM", "SIGTERM", 
-            "SIGSTKFLT", "SIGCHLD", "SIGCONT", "SIGSTOP", "SIGTSTP", "SIGTTIN", "SIGTTOU", 
-            "SIGURG", "SIGXCPU", "SIGXFSZ", "SIGVTALRM", "SIGPROF", "SIGWINCH", "SIGIO", 
-            "SIGPWR", "SIGSYS" };
-
         // ::ucontext_t * ucontext = static_cast<ucontext_t*>(arg);
-        std::cerr << "\n" << "Signal " << sig;
-        if (unsigned(sig) < sizeof(signames) / sizeof(signames[0]))
-            std::cerr << " (" << signames[unsigned(sig)] << ")";
-        std::cerr << " received\n";
+        std::cerr << "\n" << "Signal " << senf::signalName(sig) << '(' << sig << ')'
+                  << " received\n";
 
         if (sig == SIGSEGV)
             std::cerr << "Invalid memory access at " << info->si_addr << "\n";
@@ -605,7 +596,7 @@ prefix_ void senf::detail::DaemonWatcher::pipeClosed(int id)
     }
 }
 
-prefix_ void senf::detail::DaemonWatcher::sigChld()
+prefix_ void senf::detail::DaemonWatcher::sigChld(siginfo_t const &)
 {
     sigChld_ = true;
     if (coutpipe_ == -1 && cerrpipe_ == -1)
@@ -658,7 +649,7 @@ prefix_ void senf::detail::DaemonWatcher::Forwarder::addTarget(int fd)
     targets_.push_back(target);
 }
 
-prefix_ void senf::detail::DaemonWatcher::Forwarder::readData(Scheduler::EventId event)
+prefix_ void senf::detail::DaemonWatcher::Forwarder::readData(int event)
 {
     char buf[1024];
     int n (0);
@@ -692,7 +683,7 @@ prefix_ void senf::detail::DaemonWatcher::Forwarder::readData(Scheduler::EventId
     buffer_.insert(buffer_.end(), buf, buf+n);
 }
 
-prefix_ void senf::detail::DaemonWatcher::Forwarder::writeData(Scheduler::EventId event,
+prefix_ void senf::detail::DaemonWatcher::Forwarder::writeData(int event,
                                                                Targets::iterator target)
 {    
     if (event != Scheduler::EV_WRITE) {
diff --git a/Utils/Daemon/Daemon.ih b/Utils/Daemon/Daemon.ih
index 96b375c0d81ec0f0aca46a8eb32f232fcd6f9bba..0cc5c17faff70b450220ee42cf76eaafe709edbe 100644
--- a/Utils/Daemon/Daemon.ih
+++ b/Utils/Daemon/Daemon.ih
@@ -70,8 +70,8 @@ namespace detail {
             };
             typedef std::list<Target> Targets;
 
-            void readData(Scheduler::EventId event);
-            void writeData(Scheduler::EventId event, Targets::iterator target);
+            void readData(int event);
+            void writeData(int event, Targets::iterator target);
 
             Buffer buffer_;
             int src_;
@@ -82,7 +82,7 @@ namespace detail {
         };
         
         void pipeClosed(int id);
-        void sigChld();
+        void sigChld(siginfo_t const &);
         void childDied();
         void childOk();
 
diff --git a/Utils/Daemon/Daemon.test.cc b/Utils/Daemon/Daemon.test.cc
index 57a511539405550187aed48837f4fa6340ee73b1..7591434158d8a0c0e27cbca16e0e74ddddd5dfdf 100644
--- a/Utils/Daemon/Daemon.test.cc
+++ b/Utils/Daemon/Daemon.test.cc
@@ -35,6 +35,7 @@
 #include <boost/filesystem/operations.hpp>
 #include "Daemon.hh"
 #include "../Utils/Exception.hh"
+#include "../Utils/Backtrace.hh"
 
 #include "../Utils/auto_unit_test.hh"
 #include <boost/test/test_tools.hpp>
@@ -79,11 +80,19 @@ namespace {
 
     int pid;
 
+    void backtrace(int)
+    {
+        senf::backtrace(std::cerr, 100);
+        ::signal(SIGABRT, SIG_DFL);
+        ::kill(::getpid(), SIGABRT);
+    };
+
     int run(int argc, char ** argv)
     {
         pid  = ::fork();
         if (pid < 0) throw senf::SystemException("::fork()");
         if (pid == 0) {
+            signal(SIGABRT, &backtrace);
             try {
                 ::_exit(myMain(argc, argv));
             } catch (std::exception & ex) {
diff --git a/Utils/Logger/IOStreamTarget.cc b/Utils/Logger/IOStreamTarget.cc
index 487e508ca01a071377de1138144498f752d34cac..7a57ec2e4cd989ad1f926ac818570db8756c9788 100644
--- a/Utils/Logger/IOStreamTarget.cc
+++ b/Utils/Logger/IOStreamTarget.cc
@@ -71,10 +71,10 @@ prefix_ void senf::log::IOStreamTarget::v_write(time_type timestamp,
     char sep (' ');
 
     for (; i != i_end; ++i) {
-        stream_ << timestamp << sep;
+        stream_ << senf::ClockService::abstime(timestamp) << sep;
         stream_ << "[" << LEVELNAMES_[level] << "]";
         if (area != "senf::log::DefaultArea")
-            stream_ << "[" << area << "]";
+            stream_ << " [" << area << "]";
         stream_ << " " << *i << "\n";
         sep = '-';
     }
diff --git a/Utils/Logger/TimeSource.cc b/Utils/Logger/TimeSource.cc
index 61b72534572c434ce10ccf0c202bf8e81048d30e..375cce67bcbf025e055dff0119a5ba8d3d2a9225 100644
--- a/Utils/Logger/TimeSource.cc
+++ b/Utils/Logger/TimeSource.cc
@@ -46,10 +46,7 @@ prefix_ senf::log::TimeSource::~TimeSource()
 prefix_ senf::log::time_type senf::log::SystemTimeSource::operator()()
     const
 {
-    struct ::timespec tm;
-    if (::clock_gettime(CLOCK_MONOTONIC, &tm) < 0)
-        SENF_THROW_SYSTEM_EXCEPTION("::clock_gettime()");
-    return static_cast<time_type>(tm.tv_sec)*1000000000ll+tm.tv_nsec;
+    return senf::ClockService::now();
 }
 
 ///////////////////////////////cc.e////////////////////////////////////////
diff --git a/Utils/Logger/TimeSource.hh b/Utils/Logger/TimeSource.hh
index f88bb3bbd94f3f9c78d69952c4cdfcc0297d9b68..ed2c4900acc7aae4aa9f2203a41818b1ba140d55 100644
--- a/Utils/Logger/TimeSource.hh
+++ b/Utils/Logger/TimeSource.hh
@@ -29,6 +29,7 @@
 // Custom includes
 #include <boost/cstdint.hpp>
 #include <memory>
+#include "../../Scheduler/ClockService.hh"
 
 //#include "TimeSource.mpp"
 ///////////////////////////////hh.p////////////////////////////////////////
@@ -36,7 +37,7 @@
 namespace senf {
 namespace log {
 
-    typedef boost::int_fast64_t time_type;
+    typedef ClockService::clock_type time_type;
 
     /** \brief Log message time source abstract base class
 
diff --git a/Utils/signalnames.cc b/Utils/signalnames.cc
new file mode 100644
index 0000000000000000000000000000000000000000..4fc09d2f6056125a17bfcd7e69f26d98a91ef2f2
--- /dev/null
+++ b/Utils/signalnames.cc
@@ -0,0 +1,63 @@
+// $Id$
+//
+// Copyright (C) 2008 
+// Fraunhofer Institute for Open Communication Systems (FOKUS)
+// Competence Center NETwork research (NET), St. Augustin, GERMANY
+//     Stefan Bund <g0dil@berlios.de>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the
+// Free Software Foundation, Inc.,
+// 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+/** \file
+    \brief signalnames non-inline non-template implementation */
+
+#include "signalnames.hh"
+//#include "signalnames.ih"
+
+// Custom includes
+#include <boost/format.hpp>
+
+//#include "signalnames.mpp"
+#define prefix_
+///////////////////////////////cc.p////////////////////////////////////////
+
+prefix_ std::string const & senf::signalName(int signal)
+{
+    static std::string const names[] = {
+        "<unknown>", 
+        "SIGHUP", "SIGINT", "SIGQUIT", "SIGILL", "SIGTRAP", "SIGABRT", "SIGBUS", "SIGFPE", 
+        "SIGKILL", "SIGUSR1", "SIGSEGV", "SIGUSR2", "SIGPIPE", "SIGALRM", "SIGTERM", 
+        "SIGSTKFLT", "SIGCHLD", "SIGCONT", "SIGSTOP", "SIGTSTP", "SIGTTIN", "SIGTTOU", 
+        "SIGURG", "SIGXCPU", "SIGXFSZ", "SIGVTALRM", "SIGPROF", "SIGWINCH", "SIGIO", 
+        "SIGPWR", "SIGSYS" };
+
+    return names[
+        (signal <= 0 || signal > int(sizeof(names)/sizeof(names[0]))) ? 0 : signal ];
+}
+
+///////////////////////////////cc.e////////////////////////////////////////
+#undef prefix_
+//#include "signalnames.mpp"
+
+
+// Local Variables:
+// mode: c++
+// fill-column: 100
+// comment-column: 40
+// c-file-style: "senf"
+// indent-tabs-mode: nil
+// ispell-local-dictionary: "american"
+// compile-command: "scons -u test"
+// End:
diff --git a/Scheduler/Dispatcher.cci b/Utils/signalnames.hh
similarity index 73%
rename from Scheduler/Dispatcher.cci
rename to Utils/signalnames.hh
index 9364c477d051dcee64e0b2ff3250e2c93faf1bb6..d052e86b3b5c969e1ce25711b94fc33a166d847e 100644
--- a/Scheduler/Dispatcher.cci
+++ b/Utils/signalnames.hh
@@ -21,21 +21,29 @@
 // 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
 /** \file
-    \brief Dispatcher inline non-template implementation */
+    \brief signalnames public header */
 
-//#include "Dispatcher.ih"
+#ifndef HH_signalnames_
+#define HH_signalnames_ 1
 
 // Custom includes
+#include <string>
 
-#define prefix_ inline
-///////////////////////////////cci.p///////////////////////////////////////
+//#include "signalnames.mpp"
+///////////////////////////////hh.p////////////////////////////////////////
 
-prefix_ senf::scheduler::Dispatcher::Dispatcher()
-    : fdDispatcher_ (fdManager_, runner_)
-{}
+namespace senf {
 
-///////////////////////////////cci.e///////////////////////////////////////
-#undef prefix_
+    std::string const & signalName(int signal);
+
+}
+
+
+///////////////////////////////hh.e////////////////////////////////////////
+//#include "signalnames.cci"
+//#include "signalnames.ct"
+//#include "signalnames.cti"
+#endif
 
 
 // Local Variables: