Utils: Removed ErrnoException and implemented generic Exception base-class
[senf.git] / Utils / Daemon / Daemon.cc
index 34f476a..73fbf5d 100644 (file)
@@ -1,8 +1,8 @@
 // $Id$
 //
-// Copyright (C) 2007 
-// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
-// Kompetenzzentrum fuer NETwork research (NET)
+// Copyright (C) 2007
+// 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
@@ -45,8 +45,8 @@
 #define prefix_
 ///////////////////////////////cc.p////////////////////////////////////////
 
-#define LIBC_CALL(fn, args) if (fn args < 0) throwErrno(#fn "()")
-#define LIBC_CALL_RV(var, fn, args) int var (fn args); if (var < 0) throwErrno(#fn "()")
+#define LIBC_CALL(fn, args) if (fn args < 0) throw SystemException(#fn "()")
+#define LIBC_CALL_RV(var, fn, args) int var (fn args); if (var < 0) throw SystemException(#fn "()")
 
 ///////////////////////////////////////////////////////////////////////////
 // senf::Daemon
@@ -83,7 +83,7 @@ prefix_ void senf::Daemon::openLog()
     if (! stdoutLog_.empty()) {
         fd = ::open(stdoutLog_.c_str(), O_WRONLY | O_APPEND | O_CREAT, 0666);
         if (fd < 0)
-            throwErrno("::open()");
+            throw SystemException("::open()");
         stdout_ = fd;
     }
     if (stderrLog_ == stdoutLog_)
@@ -91,7 +91,7 @@ prefix_ void senf::Daemon::openLog()
     else if (! stderrLog_.empty()) {
         fd = ::open(stdoutLog_.c_str(), O_WRONLY | O_APPEND | O_CREAT, 0666);
         if (fd < 0)
-            throwErrno("::open()");
+            throw SystemException("::open()");
         stderr_ = fd;
     }
 }
@@ -110,7 +110,7 @@ namespace {
 
 prefix_ void senf::Daemon::detach()
 {
-    if (daemonize_) {
+    if (daemonize_ && ! detached_) {
         // Wow .. ouch .. 
         // To ensure all data is written to the console log file in the correct order, we suspend
         // execution here until the parent process tells us to continue via SIGUSR1: We block
@@ -139,25 +139,35 @@ prefix_ void senf::Daemon::detach()
         while (! signaled) {
             ::sigsuspend(&waitsig);
             if (errno != EINTR)
-                throwErrno("::sigsuspend()");
+                throw SystemException("::sigsuspend()");
         }
 
         LIBC_CALL( ::sigaction, (SIGUSR1, &oldact, 0) );
         LIBC_CALL( ::sigprocmask, (SIG_SETMASK, &oldsig, 0) );
+
+        detached_ = true;
     }
 }
 
+namespace {
+    /* Purposely *not* derived from std::exception */
+    struct DaemonExitException {
+        DaemonExitException(unsigned c) : code(c) {}
+        unsigned code;
+    };
+}
+
+prefix_ void senf::Daemon::exit(unsigned code)
+{
+    throw DaemonExitException(code);
+}
+
 prefix_ int senf::Daemon::start(int argc, char const ** argv)
 {
     argc_ = argc;
     argv_ = argv;
 
-#   ifdef NDEBUG
-
     try {
-
-#   endif
-
         configure();
 
         if (daemonize_) {
@@ -171,10 +181,13 @@ prefix_ int senf::Daemon::start(int argc, char const ** argv)
         }
 
         main();
+    }
+    catch (DaemonExitException & e) {
+        return e.code;
+    }
 
-#   ifdef NDEBUG
+#ifdef SENF_NO_DEBUG
 
-    }
     catch (std::exception & e) {
         std::cerr << "\n*** Fatal exception: " << e.what() << std::endl;
         return 1;
@@ -210,7 +223,8 @@ prefix_ void senf::Daemon::configure()
             std::string::size_type komma (arg.find(','));
             if (komma == std::string::npos) {
                 boost::trim(arg);
-                consoleLog(arg);
+                if (arg == std::string("none")) consoleLog("");
+                else if (!arg.empty())          consoleLog(arg);
             } else {
                 std::string arg1 (arg,0,komma);
                 std::string arg2 (arg,komma+1);
@@ -312,7 +326,7 @@ prefix_ bool senf::Daemon::pidfileCreate()
 
         if (::link(tempname.c_str(), pidfile_.c_str()) < 0) {
             if (errno != EEXIST) 
-                throwErrno("::link()");
+                throw SystemException("::link()");
         }
         else {
             struct ::stat s;
@@ -342,7 +356,7 @@ prefix_ bool senf::Daemon::pidfileCreate()
 
         LIBC_CALL( ::unlink, (tempname.c_str() ));
         if (::link(pidfile_.c_str(), tempname.c_str()) < 0) {
-            if (errno != ENOENT) throwErrno("::link()");
+            if (errno != ENOENT) throw SystemException("::link()");
             // Hmm ... the pidfile mysteriously disappeared ... try again.
             continue;
         }
@@ -405,7 +419,7 @@ prefix_ void senf::detail::DaemonWatcher::pipeClosed(int id)
         if (sigChld_)
             childDied(); // does not return
         if (::kill(childPid_, SIGUSR1) < 0)
-            if (errno != ESRCH) throwErrno("::kill()");
+            if (errno != ESRCH) throw SystemException("::kill()");
         Scheduler::instance().timeout(
             Scheduler::instance().eventTime() + ClockService::seconds(1),
             senf::membind(&DaemonWatcher::childOk, this));
@@ -422,7 +436,7 @@ prefix_ void senf::detail::DaemonWatcher::sigChld()
 prefix_ void senf::detail::DaemonWatcher::childDied()
 {
     int status (0);
-    if (::waitpid(childPid_,&status,0) < 0) throwErrno("::waitpid()");
+    if (::waitpid(childPid_,&status,0) < 0) throw SystemException("::waitpid()");
     if (WIFSIGNALED(status)) {
         ::signal(WTERMSIG(status),SIG_DFL);
         ::kill(::getpid(), WTERMSIG(status));
@@ -473,7 +487,7 @@ prefix_ void senf::detail::DaemonWatcher::Forwarder::readData(Scheduler::EventId
     while (1) {
         n = ::read(src_,buf,1024);
         if (n<0) {
-            if (errno != EINTR) throwErrno("::read()");
+            if (errno != EINTR) throw SystemException("::read()");
         } else 
             break;
     }
@@ -517,7 +531,7 @@ prefix_ void senf::detail::DaemonWatcher::Forwarder::writeData(Scheduler::EventI
 
     int w (::write(target->fd, buf, n));
     if (w < 0) {
-        if (errno != EINTR) throwErrno("::write()");
+        if (errno != EINTR) throw SystemException("::write()");
         return;
     }
     target->offset += w;