added more or less meaningful descriptions when throwing SystemExceptions
[senf.git] / senf / Utils / Daemon / Daemon.cc
index 5cda008..e2f0fec 100644 (file)
@@ -2,23 +2,28 @@
 //
 // 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
-// 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.
+// The contents of this file are subject to the Fraunhofer FOKUS Public License
+// Version 1.0 (the "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at 
+// http://senf.berlios.de/license.html
 //
-// 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.
+// The Fraunhofer FOKUS Public License Version 1.0 is based on, 
+// but modifies the Mozilla Public License Version 1.1.
+// See the full license text for the amendments.
 //
-// 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.
+// Software distributed under the License is distributed on an "AS IS" basis, 
+// WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 
+// for the specific language governing rights and limitations under the License.
+//
+// The Original Code is Fraunhofer FOKUS code.
+//
+// The Initial Developer of the Original Code is Fraunhofer-Gesellschaft e.V. 
+// (registered association), Hansastraße 27 c, 80686 Munich, Germany.
+// All Rights Reserved.
+//
+// Contributor(s):
+//   Stefan Bund <g0dil@berlios.de>
 
 /** \file
     \brief Daemon non-inline non-template implementation */
@@ -35,7 +40,9 @@
 #include <fcntl.h>
 #include <errno.h>
 #include <signal.h>
-#include <execinfo.h>
+#ifdef SENF_BACKTRACE
+   #include <execinfo.h>
+#endif
 #include <sstream>
 #include <algorithm>
 #include <boost/algorithm/string/predicate.hpp>
@@ -51,7 +58,7 @@
 
 //#include "Daemon.mpp"
 #define prefix_
-///////////////////////////////cc.p////////////////////////////////////////
+//-/////////////////////////////////////////////////////////////////////////////////////////////////
 
 #define LIBC_CALL(fn, args) if (fn args < 0) \
     SENF_THROW_SYSTEM_EXCEPTION(#fn "()")
@@ -59,7 +66,7 @@
 #define LIBC_CALL_RV(var, fn, args) \
     int var (fn args); if (var < 0) SENF_THROW_SYSTEM_EXCEPTION(#fn "()")
 
-///////////////////////////////////////////////////////////////////////////
+//-/////////////////////////////////////////////////////////////////////////////////////////////////
 // senf::Daemon
 
 prefix_ senf::Daemon::~Daemon()
@@ -67,7 +74,7 @@ prefix_ senf::Daemon::~Daemon()
     if (pidfileCreated_) {
         try {
             LIBC_CALL( ::unlink, (pidfile_.c_str()) );
-        } catch (Exception e) {
+        } catch (Exception & e) {
             // e << "; could not unlink " << pidfile_.c_str();
             // throw;
         }
@@ -84,12 +91,12 @@ prefix_ bool senf::Daemon::daemon()
     return daemonize_;
 }
 
-prefix_ int senf::Daemon::argc() 
+prefix_ int senf::Daemon::argc()
 {
     return argc_;
 }
 
-prefix_ char const ** senf::Daemon::argv() 
+prefix_ char const ** senf::Daemon::argv()
 {
     return argv_;
 }
@@ -128,8 +135,8 @@ prefix_ void senf::Daemon::openLog()
     if (! stdoutLog_.empty()) {
         fd = ::open(stdoutLog_.c_str(), O_WRONLY | O_APPEND | O_CREAT, 0666);
         if (fd < 0)
-            SENF_THROW_SYSTEM_EXCEPTION("")
-                  << " Could not open \"" << stdoutLog_ << "\" for redirecting stdout.";
+            SENF_THROW_SYSTEM_EXCEPTION(
+                  " Could not open \"" + stdoutLog_ + "\" for redirecting stdout.");
         stdout_ = fd;
     }
     if (! stderrLog_.empty()) {
@@ -137,12 +144,12 @@ prefix_ void senf::Daemon::openLog()
             stderr_ = ::dup(fd);
             if (stderr_ < 0)
                 SENF_THROW_SYSTEM_EXCEPTION("::dup()");
-        } 
+        }
         else {
             fd = ::open(stdoutLog_.c_str(), O_WRONLY | O_APPEND | O_CREAT, 0666);
             if (fd < 0)
-                SENF_THROW_SYSTEM_EXCEPTION("")
-                    << " Could not open \"" << stderrLog_ << "\" for redirecting stderr.";
+                SENF_THROW_SYSTEM_EXCEPTION(
+                    " Could not open \"" + stderrLog_ + "\" for redirecting stderr.");
             stderr_ = fd;
         }
     }
@@ -152,21 +159,21 @@ prefix_ void senf::Daemon::logReopen()
 {
     if (! stdoutLog_.empty()) {
         int fd (::open(stdoutLog_.c_str(), O_WRONLY | O_APPEND | O_CREAT, 0666));
-        if (fd < 0) 
+        if (fd < 0)
             goto error;
-        if (::dup2(fd, 1) < 0) 
+        if (::dup2(fd, 1) < 0)
             goto error;
         if (stderrLog_ == stdoutLog_) {
-            if (::dup2(fd, 2) < 0) 
+            if (::dup2(fd, 2) < 0)
                 goto error;
             return;
         }
     }
     if (! stderrLog_.empty()) {
         int fd (::open(stderrLog_.c_str(), O_WRONLY | O_APPEND | O_CREAT, 0666));
-        if (fd < 0) 
+        if (fd < 0)
             goto error;
-        if (::dup2(fd, 2) < 0) 
+        if (::dup2(fd, 2) < 0)
             goto error;
     }
     return;
@@ -192,7 +199,7 @@ namespace {
 prefix_ void senf::Daemon::detach()
 {
     if (daemonize_ && ! detached_) {
-        // Wow .. ouch .. 
+        // 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
         // SIGUSR1 and install our own signal handler saving the old handler and signal mask. Then
@@ -260,7 +267,7 @@ prefix_ int senf::Daemon::start(int argc, char const ** argv)
             if (pidfileCreate())
                 pidfileCreated_ = true;
             else {
-                std::cerr << "PID file '" << pidfile_ 
+                std::cerr << "PID file '" << pidfile_
                           << "' creation failed. Daemon running ?" << std::endl;
                 return 1;
             }
@@ -294,7 +301,7 @@ prefix_ senf::Daemon & senf::Daemon::instance()
     return *instance_;
 }
 
-////////////////////////////////////////
+//-/////////////////////////////////////////////////////////////////////////////////////////////////
 // protected members
 
 prefix_ senf::Daemon::Daemon()
@@ -307,17 +314,18 @@ prefix_ senf::Daemon::Daemon()
 
 senf::Daemon * senf::Daemon::instance_ (0);
 
-////////////////////////////////////////
+//-/////////////////////////////////////////////////////////////////////////////////////////////////
 // private members
 
 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"))
+        std::string argv (argv_[i]);
+        if (argv == "--no-daemon")
             daemonize(false);
-        else if (boost::starts_with(argv_[i], std::string("--console-log="))) {
-            std::string arg (std::string(argv_[i]).substr(14u));
+        else if (boost::starts_with(argv, "--console-log=")) {
+            std::string arg (argv.substr(14u));
             std::string::size_type komma (arg.find(','));
             if (komma == std::string::npos) {
                 boost::trim(arg);
@@ -334,7 +342,7 @@ prefix_ void senf::Daemon::configure()
                 else if (! arg2.empty() )        consoleLog(arg2, StdErr);
             }
         }
-        else if (boost::starts_with(argv_[i], std::string("--pid-file="))) 
+        else if (boost::starts_with(argv, "--pid-file="))
             pidFile(std::string(std::string(argv_[i]), 11u));
     }
 }
@@ -372,7 +380,7 @@ prefix_ void senf::Daemon::fork()
     LIBC_CALL( ::sigprocmask, (SIG_BLOCK, &cldsig, &oldsig) );
 
     if (! senf::scheduler::empty() ) {
-        std::cerr << 
+        std::cerr <<
             "\n"
             "*** WARNING ***\n"
             "Scheduler not empty before fork(). THIS MUST NOT HAPPEN.\n"
@@ -382,7 +390,7 @@ prefix_ void senf::Daemon::fork()
             "\n*** WARNING ***\n"
             "\n";
     }
-    
+
     LIBC_CALL_RV( pid, ::fork, () );
 
     if (pid == 0) {
@@ -403,7 +411,7 @@ prefix_ void senf::Daemon::fork()
 
     // Ouch ... ensure, the daemon watcher does not remove the pidfile ...
     pidfile_ = "";
-    
+
     LIBC_CALL( ::close, (coutpipe[1]) );
     LIBC_CALL( ::close, (cerrpipe[1]) );
 
@@ -437,17 +445,15 @@ prefix_ bool senf::Daemon::pidfileCreate()
         {
             std::ofstream pidf (tempname.c_str());
             if (! pidf)
-                SENF_THROW_SYSTEM_EXCEPTION("")
-                      << " Could not open pidfile \"" << tempname << "\" for output.";
+                SENF_THROW_SYSTEM_EXCEPTION(" Could not open pidfile \"" + tempname + "\" for output.");
             pidf << ::getpid() << std::endl;
             if (! pidf)
-                SENF_THROW_SYSTEM_EXCEPTION("")
-                      << " Could not write to pidfile \"" << tempname << "\".";
+                SENF_THROW_SYSTEM_EXCEPTION(" Could not write to pidfile \"" + tempname + "\".");
         }
 
         if (::link(tempname.c_str(), pidfile_.c_str()) < 0) {
-            if (errno != EEXIST) 
-                SENF_THROW_SYSTEM_EXCEPTION("") << linkErrorFormat % pidfile_ % tempname;
+            if (errno != EEXIST)
+                SENF_THROW_SYSTEM_EXCEPTION((linkErrorFormat % pidfile_ % tempname).str());
         }
         else {
             struct ::stat s;
@@ -461,8 +467,8 @@ prefix_ bool senf::Daemon::pidfileCreate()
             int old_pid (-1);
             std::ifstream pidf (pidfile_.c_str());
             if ( ! (pidf >> old_pid)
-                 || old_pid < 0 
-                 || ::kill(old_pid, 0) >= 0 
+                 || old_pid < 0
+                 || ::kill(old_pid, 0) >= 0
                  || errno == EPERM ) {
                 LIBC_CALL( ::unlink, (tempname.c_str()) );
                 return false;
@@ -480,7 +486,7 @@ prefix_ bool senf::Daemon::pidfileCreate()
         LIBC_CALL( ::unlink, (tempname.c_str() ));
         if (::link(pidfile_.c_str(), tempname.c_str()) < 0) {
             if (errno != ENOENT)
-                SENF_THROW_SYSTEM_EXCEPTION("") << linkErrorFormat % tempname % pidfile_;
+                SENF_THROW_SYSTEM_EXCEPTION( (linkErrorFormat % tempname % pidfile_).str());
             // Hmm ... the pidfile mysteriously disappeared ... try again.
             continue;
         }
@@ -493,7 +499,7 @@ prefix_ bool senf::Daemon::pidfileCreate()
                 return false;
             }
         }
-        
+
         {
             std::ofstream pidf (tempname.c_str());
             pidf << ::getpid() << std::endl;
@@ -517,9 +523,9 @@ namespace {
 
         if (sig == SIGSEGV)
             std::cerr << "Invalid memory access at " << info->si_addr << "\n";
-
+#ifdef SENF_BACKTRACE
         static void * entries[SENF_DEBUG_BACKTRACE_NUMCALLERS];
-        unsigned nEntries( ::backtrace(entries, SENF_DEBUG_BACKTRACE_NUMCALLERS) );
+        int nEntries( ::backtrace(entries, SENF_DEBUG_BACKTRACE_NUMCALLERS) );
 
         // Hack the callers address into the backtrace
         // entries[1] = reinterpret_cast<void *>(ucontext->uc_mcontext.gregs[REG_EIP]);
@@ -527,7 +533,7 @@ namespace {
         std::cerr << "Backtrace:\n";
         senf::formatBacktrace(std::cerr, entries, nEntries);
         std::cerr << "-- \n";
-
+#endif //SENF_BACKTRACE
         if (sig != SIGUSR2) {
             ::signal(sig, SIG_DFL);
             ::kill(::getpid(), sig);
@@ -536,7 +542,7 @@ namespace {
 
 }
 
-#endif
+#endif // SENF_DEBUG
 
 namespace {
     void sighupHandler(int sig)
@@ -568,13 +574,15 @@ prefix_ void senf::Daemon::installSighandlers()
     ::sigaction(SIGFPE,    &sa, NULL);
     ::sigaction(SIGBUS,    &sa, NULL);
     ::sigaction(SIGSEGV,   &sa, NULL);
+#ifdef SIGSTKFLT //SIGSTKFLT is used for stack faults on coprocessors. That condition doesn't exist on MIPS
     ::sigaction(SIGSTKFLT, &sa, NULL);
+#endif
     ::sigaction(SIGSYS,    &sa, NULL);
     ::sigaction(SIGUSR2,   &sa, NULL);
 #endif
 }
 
-///////////////////////////////////////////////////////////////////////////
+//-/////////////////////////////////////////////////////////////////////////////////////////////////
 // senf::detail::DaemonWatcher
 
 prefix_ senf::detail::DaemonWatcher::DaemonWatcher(int pid, int coutpipe, int cerrpipe,
@@ -583,8 +591,8 @@ prefix_ senf::detail::DaemonWatcher::DaemonWatcher(int pid, int coutpipe, int ce
       stderr_(stderr), sigChld_(false),
       cldSignal_ (SIGCHLD, senf::membind(&DaemonWatcher::sigChld, 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)) 
+      coutForwarder_(coutpipe_, boost::bind(&DaemonWatcher::pipeClosed, this, 1)),
+      cerrForwarder_(cerrpipe_, boost::bind(&DaemonWatcher::pipeClosed, this, 2))
 {
     coutForwarder_.addTarget(1);
     if (stdout_ >= 0)
@@ -599,7 +607,7 @@ prefix_ void senf::detail::DaemonWatcher::run()
     scheduler::process();
 }
 
-////////////////////////////////////////
+//-/////////////////////////////////////////////////////////////////////////////////////////////////
 // private members
 
 prefix_ void senf::detail::DaemonWatcher::pipeClosed(int id)
@@ -645,11 +653,11 @@ prefix_ void senf::detail::DaemonWatcher::childOk()
     scheduler::terminate();
 }
 
-///////////////////////////////////////////////////////////////////////////
+//-/////////////////////////////////////////////////////////////////////////////////////////////////
 // senf::detail::DaemonWatcher::Forwarder
 
 prefix_ senf::detail::DaemonWatcher::Forwarder::Forwarder(int src, Callback cb)
-    : src_(src), cb_(cb), 
+    : src_(src), cb_(cb),
       readevent_("senf::detail::DaemonWatcher::Forwarder::readevent", senf::membind(&Forwarder::readData, this),
                  src_, scheduler::FdEvent::EV_READ)
 {}
@@ -672,16 +680,16 @@ prefix_ void senf::detail::DaemonWatcher::Forwarder::readData(int event)
     while (1) {
         n = ::read(src_,buf,1024);
         if (n<0) {
-            if (errno != EINTR) 
+            if (errno != EINTR)
                 SENF_THROW_SYSTEM_EXCEPTION("::read()");
-        } 
-        else 
+        }
+        else
             break;
     }
 
     if (n == 0) {
         if (buffer_.empty())
-            cb_(); 
+            cb_();
         src_ = -1;
         readevent_.disable();
         return;
@@ -698,7 +706,7 @@ prefix_ void senf::detail::DaemonWatcher::Forwarder::readData(int event)
 }
 
 prefix_ void senf::detail::DaemonWatcher::Forwarder::writeData(int event, Target * target)
-{    
+{
     if (event != scheduler::FdEvent::EV_WRITE) {
         // Broken pipe while writing data ? Not much, we can do here, we just drop the data
         targets_.erase_and_destroy(Targets::current(*target),DestroyDelete());
@@ -736,7 +744,7 @@ prefix_ void senf::detail::DaemonWatcher::Forwarder::writeData(int event, Target
 #undef LIBC_CALL
 #undef LIBC_CALL_RV
 
-///////////////////////////////cc.e////////////////////////////////////////
+//-/////////////////////////////////////////////////////////////////////////////////////////////////
 #undef prefix_
 //#include "Daemon.mpp"