From: g0dil Date: Fri, 4 Apr 2008 09:34:14 +0000 (+0000) Subject: Socket: Add a 'facet<>()' member to access protocol-facets from generic socket handles X-Git-Url: http://g0dil.de/git?a=commitdiff_plain;h=d5ba3d7759212c90a5f4a25baf0dc38e290c3b64;p=senf.git Socket: Add a 'facet<>()' member to access protocol-facets from generic socket handles Scheduler: Add ClockService::from_time_t and from_timeval Utils: Implement generic backtrace helper Utils/Daemon: Catch fatal signals (plus SIGUSR2) and show a backtrace in debug builds git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@780 270642c3-0616-0410-b53a-bc976706d245 --- diff --git a/Scheduler/ClockService.cci b/Scheduler/ClockService.cci index 41cc91c..a26d937 100644 --- a/Scheduler/ClockService.cci +++ b/Scheduler/ClockService.cci @@ -47,6 +47,16 @@ prefix_ senf::ClockService::clock_type senf::ClockService::clock(abstime_type ti return instance().clock_m(time); } +prefix_ senf::ClockService::clock_type senf::ClockService::from_time_t(time_t const & time) +{ + return clock( boost::posix_time::from_time_t(time) ); +} + +prefix_ senf::ClockService::clock_type senf::ClockService::from_timeval(timeval const & time) +{ + return from_time_t(time.tv_sec) + ClockService::microseconds(time.tv_usec); +} + prefix_ senf::ClockService::clock_type senf::ClockService::nanoseconds(clock_type v) { return v; diff --git a/Scheduler/ClockService.hh b/Scheduler/ClockService.hh index ba9b2ac..04bcc1a 100644 --- a/Scheduler/ClockService.hh +++ b/Scheduler/ClockService.hh @@ -27,6 +27,7 @@ #define HH_ClockService_ 1 // Custom includes +#include #include #include #include @@ -130,6 +131,16 @@ namespace senf { corresponding clock value. \see abstime */ + static clock_type from_time_t(time_t const & time); + ///< Convert legacy time_t to clock value + /**< This member converts an absolute time value + represented as a time_t value into a clock value */ + + static clock_type from_timeval(timeval const & time); + ///< Convert legacy timeval to clock value + /**< This member converts an absolute time value + represented as a timeval value into a clock value */ + static clock_type nanoseconds(clock_type v); static clock_type microseconds(clock_type v); static clock_type milliseconds(clock_type v); diff --git a/Socket/SocketHandle.cti b/Socket/SocketHandle.cti index 39b3273..cbd9089 100644 --- a/Socket/SocketHandle.cti +++ b/Socket/SocketHandle.cti @@ -187,6 +187,17 @@ prefix_ std::string senf::SocketHandle::dumpState(unsigned lod) return detail::dumpState(map); } +template +template +prefix_ Facet const & senf::SocketHandle::facet() + +{ + try { + return dynamic_cast(protocol()); + } + SENF_WRAP_EXC(std::bad_cast) +} + /////////////////////////////////////////////////////////////////////////// // senf::ProtocolSocketBody diff --git a/Socket/SocketHandle.hh b/Socket/SocketHandle.hh index 6d36be8..867d0aa 100644 --- a/Socket/SocketHandle.hh +++ b/Socket/SocketHandle.hh @@ -147,6 +147,16 @@ namespace senf { every derived class. See the state() documentation. */ + template + Facet const & facet(); ///< Access a protocol facet + /**< This member will try to access the given protocol facet + of the socket. If \a Facet is a valid facet of the + protocol, it is returned, otherwise \c std::bad_cast + will be thrown. + \throws std::bad_cast if \a Facet is not a protocol + facet of this socket + \returns the \a Facet protocol facet of this socket */ + protected: explicit SocketHandle(std::auto_ptr body); ///< Initialize SocketHandle providing the protocol diff --git a/Socket/SocketHandle.test.cc b/Socket/SocketHandle.test.cc index 63fff9e..c88c636 100644 --- a/Socket/SocketHandle.test.cc +++ b/Socket/SocketHandle.test.cc @@ -94,6 +94,8 @@ BOOST_AUTO_UNIT_TEST(socketHandle) "socket.protocol: senf::test::SomeSocketProtocol\n" "socket.protocol.policy: senf::SocketPolicy\n" "socket.server: false\n" ); + + BOOST_CHECK_NO_THROW( myh.facet() ); } // Ensure, the destructor is called and calls the correct close() implementation diff --git a/Utils/Backtrace.cc b/Utils/Backtrace.cc new file mode 100644 index 0000000..09239c8 --- /dev/null +++ b/Utils/Backtrace.cc @@ -0,0 +1,89 @@ +// $Id$ +// +// Copyright (C) 2008 +// Fraunhofer Institute for Open Communication Systems (FOKUS) +// Competence Center NETwork research (NET), St. Augustin, GERMANY +// Stefan Bund +// +// 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 Backtrace non-inline non-template implementation */ + +#include "Backtrace.hh" +//#include "Backtrace.ih" + +// Custom includes +#include +#include +#include + +//#include "Backtrace.mpp" +#define prefix_ +///////////////////////////////cc.p//////////////////////////////////////// + +prefix_ void senf::formatBacktrace(std::ostream & os, void ** backtrace, unsigned numEntries) +{ + char ** symbols (::backtrace_symbols(backtrace, numEntries)); + + static boost::regex const backtraceRx + ("(.*)\\((.*)\\+(0x[0-9a-f]+)\\) \\[(0x[0-9a-f]+)\\]"); + enum { File = 1, + Symbol = 2, + Offset = 3, + Address = 4 }; + + for (unsigned i=0; i +// +// 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 Backtrace public header */ + +#ifndef HH_Backtrace_ +#define HH_Backtrace_ 1 + +// Custom includes +#include + +//#include "Backtrace.mpp" +///////////////////////////////hh.p//////////////////////////////////////// + +namespace senf { + + void formatBacktrace(std::ostream & os, void ** backtrace, unsigned numEntries); + +} + +///////////////////////////////hh.e//////////////////////////////////////// +//#include "Backtrace.cci" +//#include "Backtrace.ct" +//#include "Backtrace.cti" +#endif + + +// 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/Utils/Daemon/Daemon.cc b/Utils/Daemon/Daemon.cc index 1a684a5..fe55821 100644 --- a/Utils/Daemon/Daemon.cc +++ b/Utils/Daemon/Daemon.cc @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -41,6 +42,10 @@ #include #include "../Exception.hh" #include "../membind.hh" +#include "../Backtrace.hh" + +// #define __USE_GNU +#include //#include "Daemon.mpp" #define prefix_ @@ -196,6 +201,7 @@ prefix_ int senf::Daemon::start(int argc, char ** argv) openLog(); fork(); } + installSighandlers(); if (! pidfile_.empty()) { if (pidfileCreate()) pidfileCreated_ = true; @@ -417,6 +423,69 @@ prefix_ bool senf::Daemon::pidfileCreate() return true; } + +#ifdef SENF_DEBUG + +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(arg); + std::cerr << "\n" << "Signal " << sig; + if (unsigned(sig) < sizeof(signames) / sizeof(signames[0])) + std::cerr << " (" << signames[unsigned(sig)] << ")"; + std::cerr << " received\n"; + + if (sig == SIGSEGV) + std::cerr << "Invalid memory access at " << info->si_addr << "\n"; + + static void * entries[SENF_DEBUG_BACKTRACE_NUMCALLERS]; + unsigned nEntries( ::backtrace(entries, SENF_DEBUG_BACKTRACE_NUMCALLERS) ); + + // Hack the callers address into the backtrace + // entries[1] = reinterpret_cast(ucontext->uc_mcontext.gregs[REG_EIP]); + + std::cerr << "Backtrace:\n"; + senf::formatBacktrace(std::cerr, entries, nEntries); + std::cerr << "-- \n"; + + if (sig != SIGUSR2) { + ::signal(sig, SIG_DFL); + ::kill(::getpid(), sig); + } + } + +} + +#endif + +prefix_ void senf::Daemon::installSighandlers() +{ +#ifdef SENF_DEBUG + struct ::sigaction sa; + sa.sa_sigaction = &fatalSignalsHandler; + ::sigemptyset(&sa.sa_mask); + sa.sa_flags = SA_RESTART | SA_SIGINFO; + + ::sigaction(SIGILL, &sa, NULL); + ::sigaction(SIGTRAP, &sa, NULL); + ::sigaction(SIGABRT, &sa, NULL); + ::sigaction(SIGFPE, &sa, NULL); + ::sigaction(SIGBUS, &sa, NULL); + ::sigaction(SIGSEGV, &sa, NULL); + ::sigaction(SIGSTKFLT, &sa, NULL); + ::sigaction(SIGSYS, &sa, NULL); + ::sigaction(SIGUSR2, &sa, NULL); +#endif +} + /////////////////////////////////////////////////////////////////////////// // senf::detail::DaemonWatcher diff --git a/Utils/Daemon/Daemon.hh b/Utils/Daemon/Daemon.hh index 25b8e60..d0ba4a7 100644 --- a/Utils/Daemon/Daemon.hh +++ b/Utils/Daemon/Daemon.hh @@ -154,9 +154,9 @@ namespace senf { successful startup. */ int argc(); ///< Access command line parameter count - char ** argv(); ///< Access command line parameters + char ** argv(); ///< Access command line parameters - static void exit(unsigned code=0); ///< Terminate daemon with failure + static void exit(unsigned code=0); ///< Terminate daemon with failure ///\} @@ -195,10 +195,10 @@ namespace senf { This member is only called, if the default main() implementation is not overridden. */ private: - void openLog(); void fork(); bool pidfileCreate(); + void installSighandlers(); int argc_; char ** argv_; diff --git a/Utils/Exception.cc b/Utils/Exception.cc index a651239..b2c750f 100644 --- a/Utils/Exception.cc +++ b/Utils/Exception.cc @@ -30,12 +30,7 @@ #include #include #include "../config.hh" - -// Copied from the binutils sources -#define HAVE_DECL_BASENAME 1 -#define HAVE_DECL_ASPRINTF 1 -#define HAVE_DECL_VASPRINTF 1 -#include "impl/demangle.h" +#include "Backtrace.hh" #define prefix_ ///////////////////////////////cc.p//////////////////////////////////////// @@ -48,30 +43,12 @@ prefix_ void senf::ExceptionMixin::addBacktrace() { void * entries[SENF_DEBUG_BACKTRACE_NUMCALLERS]; unsigned nEntries( ::backtrace(entries, SENF_DEBUG_BACKTRACE_NUMCALLERS) ); - char ** symbols = ::backtrace_symbols(entries, nEntries); - + std::stringstream ss; ss << "\nException at\n"; - for (unsigned i=0; i