Scheduler: Implement PollTimerSource
[senf.git] / Utils / Daemon / Daemon.cc
index 89dbcec..8cbf98f 100644 (file)
@@ -31,6 +31,7 @@
 #include <sys/stat.h>
 #include <sys/wait.h>
 #include <unistd.h>
+#include <limits.h>
 #include <fcntl.h>
 #include <errno.h>
 #include <signal.h>
@@ -88,7 +89,7 @@ prefix_ int senf::Daemon::argc()
     return argc_;
 }
 
-prefix_ char ** senf::Daemon::argv() 
+prefix_ char const ** senf::Daemon::argv() 
 {
     return argv_;
 }
@@ -106,7 +107,7 @@ namespace {
 
 prefix_ void senf::Daemon::removeDaemonArgs()
 {
-    char ** last (std::remove_if(argv_+1, argv_+argc_, IsDaemonOpt()));
+    char const ** last (std::remove_if(argv_+1, argv_+argc_, IsDaemonOpt()));
     *last = 0;
     argc_ = last - argv_;
 }
@@ -131,8 +132,11 @@ prefix_ void senf::Daemon::openLog()
                   << " Could not open \"" << stdoutLog_ << "\" for redirecting stdout.";
         stdout_ = fd;
     }
-    if (stderrLog_ == stdoutLog_)
-        stderr_ = fd;
+    if (stderrLog_ == stdoutLog_) {
+        stderr_ = ::dup(fd);
+        if (stderr_ < 0)
+            SENF_THROW_SYSTEM_EXCEPTION("::dup()");
+    } 
     else if (! stderrLog_.empty()) {
         fd = ::open(stdoutLog_.c_str(), O_WRONLY | O_APPEND | O_CREAT, 0666);
         if (fd < 0)
@@ -237,7 +241,7 @@ prefix_ void senf::Daemon::exit(unsigned code)
     throw DaemonExitException(code);
 }
 
-prefix_ int senf::Daemon::start(int argc, char ** argv)
+prefix_ int senf::Daemon::start(int argc, char const ** argv)
 {
     argc_ = argc;
     argv_ = argv;
@@ -306,6 +310,7 @@ senf::Daemon * senf::Daemon::instance_ (0);
 
 prefix_ void senf::Daemon::configure()
 {
+    // int i (not unsigned) since argc_ is int ...
     for (int i (1); i<argc_; ++i) {
         if (argv_[i] == std::string("--no-daemon"))
             daemonize(false);
@@ -363,6 +368,15 @@ prefix_ void senf::Daemon::fork()
     ::sigemptyset(&cldsig);
     LIBC_CALL( ::sigaddset, (&cldsig, SIGCHLD) );
     LIBC_CALL( ::sigprocmask, (SIG_BLOCK, &cldsig, &oldsig) );
+
+    if (! senf::scheduler::empty() )
+        std::cerr << 
+            "\n"
+            "*** WARNING ***\n"
+            "Scheduler not empty before fork(). THIS MUST NOT HAPPEN.\n"
+            "The scheduler will be reinitialized by the fork() and lose all registrations.\n"
+            "*** WARNING ***\n"
+            "\n";
     
     LIBC_CALL_RV( pid, ::fork, () );
 
@@ -378,7 +392,7 @@ prefix_ void senf::Daemon::fork()
         LIBC_CALL( ::setsid, () );
         LIBC_CALL( ::sigprocmask, (SIG_SETMASK, &oldsig, 0) );
 
-        senf::Scheduler::instance().restart();
+        senf::scheduler::restart();
         return;
     }
 
@@ -388,7 +402,7 @@ prefix_ void senf::Daemon::fork()
     LIBC_CALL( ::close, (coutpipe[1]) );
     LIBC_CALL( ::close, (cerrpipe[1]) );
 
-    senf::Scheduler::instance().restart();
+    senf::scheduler::restart();
 
     detail::DaemonWatcher watcher (pid, coutpipe[0], cerrpipe[0], stdout_, stderr_);
     watcher.run();
@@ -563,7 +577,7 @@ prefix_ senf::detail::DaemonWatcher::DaemonWatcher(int pid, int coutpipe, int ce
     : childPid_(pid), coutpipe_(coutpipe), cerrpipe_(cerrpipe), stdout_(stdout),
       stderr_(stderr), sigChld_(false),
       cldSignal_ (SIGCHLD, senf::membind(&DaemonWatcher::sigChld, this)),
-      timer_ ("DaemanWatcher watchdog", senf::membind(&DaemonWatcher::childOk, this)),
+      timer_ ("senf::detail::DaemonWatcher::childOk", senf::membind(&DaemonWatcher::childOk, this)),
       coutForwarder_(coutpipe_, boost::bind(&DaemonWatcher::pipeClosed, this, 1)), 
       cerrForwarder_(cerrpipe_, boost::bind(&DaemonWatcher::pipeClosed, this, 2)) 
 {
@@ -577,7 +591,7 @@ prefix_ senf::detail::DaemonWatcher::DaemonWatcher(int pid, int coutpipe, int ce
 
 prefix_ void senf::detail::DaemonWatcher::run()
 {
-    Scheduler::instance().process();
+    scheduler::process();
 }
 
 ////////////////////////////////////////
@@ -595,7 +609,7 @@ prefix_ void senf::detail::DaemonWatcher::pipeClosed(int id)
             childDied(); // does not return
         if (::kill(childPid_, SIGUSR1) < 0 && errno != ESRCH)
             SENF_THROW_SYSTEM_EXCEPTION("::kill()");
-        timer_.timeout(Scheduler::instance().eventTime() + ClockService::seconds(1));
+        timer_.timeout(scheduler::eventTime() + ClockService::seconds(1));
     }
 }
 
@@ -623,33 +637,26 @@ prefix_ void senf::detail::DaemonWatcher::childDied()
 
 prefix_ void senf::detail::DaemonWatcher::childOk()
 {
-    Scheduler::instance().terminate();
+    scheduler::terminate();
 }
 
 ///////////////////////////////////////////////////////////////////////////
 // senf::detail::DaemonWatcher::Forwarder
 
 prefix_ senf::detail::DaemonWatcher::Forwarder::Forwarder(int src, Callback cb)
-    : src_(src), cb_(cb)
-{
-    Scheduler::instance().add(src_, senf::membind(&Forwarder::readData, this),
-                              Scheduler::EV_READ);
-}
+    : src_(src), cb_(cb), 
+      readevent_("senf::detail::DaemonWatcher::Forwarder::readevent", senf::membind(&Forwarder::readData, this),
+                 src_, scheduler::FdEvent::EV_READ)
+{}
 
 prefix_ senf::detail::DaemonWatcher::Forwarder::~Forwarder()
 {
-    if (src_ != -1)
-        Scheduler::instance().remove(src_);
-    
-    for (Targets::iterator i (targets_.begin()); i != targets_.end(); ++i)
-        if (i->offset >= buffer_.size())
-            Scheduler::instance().remove(i->fd);
+    targets_.clear_and_destroy(DestroyDelete());
 }
 
 prefix_ void senf::detail::DaemonWatcher::Forwarder::addTarget(int fd)
 {
-    Target target = { fd, 0 };
-    targets_.push_back(target);
+    targets_.push_back(*(new Target(*this, fd)));
 }
 
 prefix_ void senf::detail::DaemonWatcher::Forwarder::readData(int event)
@@ -660,17 +667,18 @@ prefix_ void senf::detail::DaemonWatcher::Forwarder::readData(int event)
     while (1) {
         n = ::read(src_,buf,1024);
         if (n<0) {
-            if (errno != EINTR) SENF_THROW_SYSTEM_EXCEPTION("::read()");
-        } else 
+            if (errno != EINTR) 
+                SENF_THROW_SYSTEM_EXCEPTION("::read()");
+        } 
+        else 
             break;
     }
 
     if (n == 0) {
-        // Hangup
-        Scheduler::instance().remove(src_);
         if (buffer_.empty())
             cb_(); 
         src_ = -1;
+        readevent_.disable();
         return;
     }
 
@@ -679,20 +687,16 @@ prefix_ void senf::detail::DaemonWatcher::Forwarder::readData(int event)
 
     for (Targets::iterator i (targets_.begin()); i != targets_.end(); ++i)
         if (i->offset >= buffer_.size())
-            Scheduler::instance().add( i->fd, 
-                                       boost::bind(&Forwarder::writeData, this, _1, i),
-                                       Scheduler::EV_WRITE );
+            i->writeevent.enable();
 
     buffer_.insert(buffer_.end(), buf, buf+n);
 }
 
-prefix_ void senf::detail::DaemonWatcher::Forwarder::writeData(int event,
-                                                               Targets::iterator target)
+prefix_ void senf::detail::DaemonWatcher::Forwarder::writeData(int event, Target * target)
 {    
-    if (event != Scheduler::EV_WRITE) {
+    if (event != scheduler::FdEvent::EV_WRITE) {
         // Broken pipe while writing data ? Not much, we can do here, we just drop the data
-        Scheduler::instance().remove(target->fd);
-        targets_.erase(target);
+        targets_.erase_and_destroy(Targets::current(*target),DestroyDelete());
         if (targets_.empty() && src_ == -1)
             cb_();
         return;
@@ -719,7 +723,7 @@ prefix_ void senf::detail::DaemonWatcher::Forwarder::writeData(int event,
         i->offset -= n;
 
     if (target->offset >= buffer_.size())
-        Scheduler::instance().remove(target->fd);
+        target->writeevent.disable();
     if (src_ == -1 && (buffer_.empty() || targets_.empty()))
         cb_();
 }