--- /dev/null
+/** @file
+ * @brief provides a little base class for classes wich are used in conjunction with shared pointer.
+ *
+ * @author Reinhard Pfau \<reinhard.pfau@intra2net.com\>
+ *
+ * @copyright © Copyright 2008 Intra2Net AG
+ * @license commercial
+ * @contact info@intra2net.com
+ *
+ */
+
+#ifndef __I2N_POINTER_FUNC_HPP__
+#define __I2N_POINTER_FUNC_HPP__
+
+#include <boost/shared_ptr.hpp>
+#include <boost/enable_shared_from_this.hpp>
+
+namespace I2n
+{
+
+
+/**
+ * @brief base class for classes used as type with shared pointers.
+ *
+ * Must be virtually inherited by (base) classes which are used in
+ * conjunction with shared pointers.
+ *
+ * Allows these classes (and its derived classes) to protect their methods
+ * against preliminary deletion by giving them the possibility to obtain
+ * a shared pointer to themself.
+ */
+class SharedBase
+: public boost::enable_shared_from_this< SharedBase >
+{
+ public:
+ typedef boost::shared_ptr< SharedBase > BasePtrType;
+ typedef boost::shared_ptr< SharedBase > PtrType;
+
+ public:
+ SharedBase();
+ virtual ~SharedBase();
+
+
+ /**
+ * @brief gets a shared pointer to itself if applicable.
+ * @return the shared pointer (to the base class); empty if not applicable.
+ *
+ * The method catches the @a boost::bad_weak_ptr exception and ignores it.
+ * So this method doesn't throw if the instance is not held by a shared pointer.
+ */
+ BasePtrType get_base_ptr()
+ {
+ BasePtrType result;
+ try {
+ result = shared_from_this();
+ }
+ catch (boost::bad_weak_ptr)
+ {
+ }
+ return result;
+ } // eo get_base_ptr
+
+
+ /**
+ * @brief gets a shared pointer to itself with a specific (derived) type.
+ * @tparam T the desired type for the shared pointer.
+ * @return the shared pointer (to the desired type); empty if not applicable.
+ *
+ * The method catches the @a boost::bad_weak_ptr exception and ignores it.
+ * So this method doesn't throw if the instance is not held by a shared pointer.
+ */
+ template< class T >
+ boost::shared_ptr< T > get_ptr_as()
+ {
+ boost::shared_ptr< T > result;
+ BasePtrType ptr;
+ try {
+ ptr = shared_from_this();
+ }
+ catch (boost::bad_weak_ptr)
+ {
+ }
+ if (ptr)
+ {
+ result= boost::shared_dynamic_cast< T >(ptr);
+ }
+ return result;
+ } // eo get_ptr_as
+
+
+}; // eo SharedBase
+
+typedef SharedBase::PtrType SharedBasePtr;
+
+} // eo namespace I2n
+
+#endif
--- /dev/null
+/** @file
+ * @brief implementation of wrapper and tools for signal related stuff.
+ *
+ * @copyright © Copyright 2007-2008 by Intra2net AG
+ * @license commercial
+ *
+ * info@intra2net.com
+ */
+
+#include "signalfunc.hpp"
+
+#include <algorithm>
+
+#include <unistd.h>
+#include <signal.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <errno.h>
+#include <pwd.h>
+#include <grp.h>
+
+#include <containerfunc.hpp>
+
+
+namespace I2n
+{
+namespace SystemTools
+{
+
+
+namespace
+{
+
+/**
+ * helper for using sigaddset() as unary function within (STL) algorithms.
+ */
+struct SigAddSet
+{
+ sigset_t *m_set;
+ SigAddSet(sigset_t *set) : m_set(set) {}
+ int operator() (int sig) { return sigaddset(m_set,sig); }
+}; // eo struct SigAddSet
+
+
+
+/**
+ * blocks the given signals while existing.
+ *
+ * This class is the real (internal) implementation of the @a SignalBlocker .
+ *
+ * @internal This internal implementation is used to avoid including signal.h within the header file.
+ * This way, we can keep the header clean; and hide all the internals in the implementation.
+ */
+class _ScopedSignalBlocker : public SystemTools::Detail::SObject
+{
+ public:
+ _ScopedSignalBlocker(const std::vector<SystemTools::Signal>& sigs);
+ ~_ScopedSignalBlocker();
+
+ bool successful() const {return m_set; }
+
+ protected:
+ sigset_t m_sigset[1];
+ sigset_t m_oldsigset[1];
+ bool m_set;
+}; // eo _ScopedSignalBlocker
+
+
+/**
+ * Blocks the given signals.
+ *
+ * Constructs a sigset from the passed signals; and calls sigprocmask to block them.
+ * In case of interruption with EINTR during the call, the call is repeated some times
+ * to get the desired signals blocked.
+ *
+ * @param sigs the vector with the siganls which should be blocked.
+ */
+_ScopedSignalBlocker::_ScopedSignalBlocker(const std::vector<SystemTools::Signal>& sigs)
+{
+ sigemptyset(m_sigset);
+
+ // fill in signals
+ std::for_each(sigs.begin(), sigs.end(), SigAddSet(m_sigset) );
+
+ int res;
+ for(int cnt=1000; cnt-->0;)
+ {
+ res= sigprocmask(SIG_BLOCK,m_sigset, m_oldsigset);
+ if (!res || errno!=EINTR) break;
+ }
+ m_set= (res==0);
+} // eo _ScopedSignalBlocker::_ScopedSignalBlocker()
+
+
+/**
+ * Unblocks the signals by restoring the original block mask.
+ */
+_ScopedSignalBlocker::~_ScopedSignalBlocker()
+{
+ int res;
+ if (!m_set) return;
+ for(int cnt=1000; cnt-->0;)
+ {
+ res= sigprocmask(SIG_SETMASK, m_oldsigset, NULL);
+ if (!res || errno!=EINTR) break;
+ }
+} // eo _ScopedSignalBlocker::~_ScopedSignalBlocker()
+
+
+
+} // eo namespace <anonymous>
+
+
+/*************************************************************************\
+\*************************************************************************/
+
+
+
+/*
+ * Signal
+ */
+/// @cond
+
+const int Signal::VOID= 0;
+
+// helper macro to import the signal nums:
+#define IMPORT(sig) const int Signal::sig = SIG ## sig
+
+IMPORT(HUP);
+IMPORT(INT);
+IMPORT(QUIT);
+IMPORT(ILL);
+IMPORT(TRAP);
+IMPORT(ABRT);
+IMPORT(IOT);
+IMPORT(BUS);
+IMPORT(FPE);
+IMPORT(KILL);
+IMPORT(USR1);
+IMPORT(SEGV);
+IMPORT(USR2);
+IMPORT(PIPE);
+IMPORT(ALRM);
+IMPORT(TERM);
+IMPORT(STKFLT);
+IMPORT(CLD);
+IMPORT(CHLD);
+IMPORT(CONT);
+IMPORT(STOP);
+IMPORT(TSTP);
+IMPORT(TTIN);
+IMPORT(TTOU);
+IMPORT(URG);
+IMPORT(XCPU);
+IMPORT(XFSZ);
+IMPORT(VTALRM);
+IMPORT(PROF);
+IMPORT(WINCH);
+IMPORT(POLL);
+IMPORT(IO);
+IMPORT(PWR);
+IMPORT(SYS);
+
+// remove helper macro
+#undef IMPORT
+
+/// @endcond
+
+int Signal::RT(int num)
+{
+ return SIGRTMIN + num;
+} // eo Signal::RT
+
+
+/*
+ * SignalCode
+ */
+
+
+/// @cond
+
+// basically: define apropriate CODE macro and copy the CODE() parts from hpp:
+
+#undef CODE
+#define CODE(name) const int SignalCode::name = SI_ ## name
+ CODE(USER); CODE(QUEUE); CODE(TIMER); CODE(MESGQ);
+ CODE(ASYNCIO);
+#undef SIGIO
+ CODE(SIGIO);
+#undef CODE
+#define CODE(name) const int SignalCode::ILL::name = ILL_ ## name
+ CODE(ILLOPC); CODE(ILLOPN); CODE(ILLADR); CODE(ILLTRP);
+ CODE(PRVOPC); CODE(PRVREG); CODE(COPROC); CODE(BADSTK);
+#undef CODE
+#define CODE(name) const int SignalCode::FPE::name = FPE_ ## name
+ CODE(INTDIV); CODE(INTOVF); CODE(FLTDIV); CODE(FLTOVF);
+ CODE(FLTUND); CODE(FLTRES); CODE(FLTINV); CODE(FLTSUB);
+#undef CODE
+#define CODE(name) const int SignalCode::SEGV::name = SEGV_ ## name
+ CODE(MAPERR); CODE(ACCERR);
+#undef CODE
+#define CODE(name) const int SignalCode::BUS::name = BUS_ ## name
+ CODE(ADRALN); CODE(ADRERR); CODE(OBJERR);
+#undef CODE
+#define CODE(name) const int SignalCode::TRAP::name = TRAP_ ## name
+ CODE(BRKPT); CODE(TRACE);
+#undef CODE
+#define CODE(name) const int SignalCode::CHLD::name = CLD_ ## name
+ CODE(EXITED); CODE(KILLED); CODE(DUMPED); CODE(TRAPPED);
+ CODE(STOPPED); CODE(CONTINUED);
+#undef CODE
+#define CODE(name) const int SignalCode::POLL::name = POLL_ ## name
+ CODE(IN); CODE(OUT); CODE(MSG); CODE(ERR); CODE(PRI); CODE(HUP);
+#undef CODE
+/// @endcond
+
+/*
+ * ScopedSignalBlocker
+ */
+
+
+/**
+ * Blocks the given signal.
+ * @param sig the signal which should be blocked.
+ */
+ScopedSignalBlocker::ScopedSignalBlocker(Signal sig)
+{
+ Implementation = new _ScopedSignalBlocker( TransientPushBackFiller< Signal, std::vector >()(sig) );
+} // eo ScopedSignalBlocker::ScopedSignalBlocker
+
+
+ScopedSignalBlocker::ScopedSignalBlocker(Signal sig1, Signal sig2)
+{
+ Implementation = new _ScopedSignalBlocker( TransientPushBackFiller< Signal, std::vector >()(sig1)(sig2) );
+} // eo ScopedSignalBlocker::ScopedSignalBlocker
+
+
+ScopedSignalBlocker::ScopedSignalBlocker(Signal sig1, Signal sig2, Signal sig3)
+{
+ Implementation = new _ScopedSignalBlocker( TransientPushBackFiller< Signal, std::vector >()(sig1)(sig2)(sig3) );
+} // eo ScopedSignalBlocker::ScopedSignalBlocker
+
+
+/**
+ * Blocks the given signals.
+ * @param sigs vector with the signals which should be blocked.
+ */
+ScopedSignalBlocker::ScopedSignalBlocker(const std::vector<Signal>& sigs)
+{
+ Implementation = new _ScopedSignalBlocker( sigs );
+} // eo ScopedSignalBlocker::ScopedSignalBlocker
+
+
+/**
+ * Unblocks the signals by restoring the previous blocking list.
+ */
+ScopedSignalBlocker::~ScopedSignalBlocker()
+{
+ if (Implementation)
+ {
+ delete Implementation;
+ Implementation= NULL;
+ }
+} // eo ScopedSignalBlocker::ScopedSignalBlocker
+
+
+
+/*
+** signal handling
+*/
+
+typedef std::map< int, struct sigaction > SignalActionMap;
+
+namespace {
+
+SignalActionMap original_signal_action;
+
+} // eo namespace <anonymous>
+
+
+/**
+ * @brief installs a new signal action.
+ * @param sig the signal
+ * @param new_action the new signal action.
+ * @return @a true iff the new signal action was succesfully installed.
+ *
+ * Remembers the original value of the signal handler for later restoring.
+ */
+bool install_signal_handler(
+ Signal sig,
+ struct sigaction& new_action
+)
+{
+ struct sigaction old_action[1];
+ int signum= sig;
+ int res= ::sigaction(signum, &new_action, old_action);
+ if (0 == res)
+ {
+ SignalActionMap::iterator it= original_signal_action.find(signum);
+ if (it == original_signal_action.end())
+ {
+ original_signal_action[signum] = *old_action;
+ }
+ }
+ return (0 == res);
+} // eo install_signal_handler(int,sigaction&)
+
+
+/**
+ * @brief installs a simple signal handler.
+ * @param sig the signal.
+ * @param handler pointer to the signal handler.
+ * @return @a true iff the handler was successfully installed.
+ *
+ * Remembers the original value of the signal handler for later restoring.
+ */
+bool install_signal_handler(
+ Signal sig,
+ void(*handler)(int)
+)
+{
+ struct sigaction new_action;
+ new_action.sa_handler= handler;
+ sigemptyset( &new_action.sa_mask );
+ new_action.sa_flags= 0;
+ new_action.sa_restorer= NULL;
+ return install_signal_handler(sig, new_action);
+} // eo install_signal_handler(signum,void(*)(int))
+
+
+
+/**
+ * @brief installs a signal action handler.
+ * @param sig the signal
+ * @param handler pointer to the signal action handler.
+ * @return @a true iff the action handler was successfully installed.
+ *
+ * Remembers the original value of the signal handler for later restoring.
+ */
+bool install_signal_handler(
+ Signal sig,
+ void(*handler)(int,struct siginfo*,void*)
+)
+{
+ struct sigaction new_action;
+ new_action.sa_sigaction= handler;
+ sigemptyset( &new_action.sa_mask );
+ new_action.sa_flags= SA_SIGINFO;
+ new_action.sa_restorer= NULL;
+ return install_signal_handler(sig, new_action);
+} // eo install_signal_handler(signum,void(*)(int,siginfo_t*,void*))
+
+
+/**
+ * @brief ignores a signal.
+ * @param sig the signal
+ * @return @a true iff the ignore handler was successfully installed.
+ *
+ * Remembers the original value of the signal handler for later restoring.
+ */
+bool ignore_signal(Signal sig)
+{
+ return install_signal_handler(sig, SIG_IGN );
+} // eo ignore_signal(Signal)
+
+
+/**
+ * @brief enables the default signal handler.
+ * @param sig the signal
+ * @return @a true iff the default handler was successfully installed.
+ *
+ * Remembers the original value of the signal handler for later restoring.
+ */
+bool install_default_signal_handler(Signal sig)
+{
+ return install_signal_handler(sig, SIG_DFL );
+} // eo install_default_signal_handler(Signal)
+
+
+/**
+ * @brief restores a signal handle to its original value.
+ * @param sig the signal.
+ * @return @a true iff the handler was sucessfully restored.
+ */
+bool restore_signal_handler(Signal sig)
+{
+ int signum= sig;
+ SignalActionMap::iterator it= original_signal_action.find(signum);
+ int res= -1;
+ if (it != original_signal_action.end())
+ {
+ res= ::sigaction(signum, &(it->second), NULL);
+ if (0 == res)
+ {
+ original_signal_action.erase(it);
+ }
+ }
+ return (0 == res);
+} // eo restore_signal_handler
+
+
+
+/**
+ * @brief convenience function; send's a signal to a process.
+ * @param pid PID of the process which should recive the signal.
+ * @param signal the signal to send.
+ * @return @a true iff sending of the signal succeeded.
+ */
+bool send_signal( pid_t pid, Signal signal)
+{
+ return ::kill(pid, signal.Value) == 0;
+} // eo send_signal(pid_t,Signal)
+
+
+
+} // eo namespace SystemTools
+} // eo namespace I2n
--- /dev/null
+/** @file
+ * @brief provides wrapper and tools for signal related stuff.
+ *
+ *
+ * @copyright © Copyright 2007-2008 by Intra2net AG
+ * @license commercial
+ * @contact info@intra2net.com
+ *
+ * @bug
+ * Although most stuff should work under most POSIX like systems;
+ * some funcs might be very linux related.
+ * (But at least we use that lib currently under linux only.)
+ */
+
+#ifndef _I2N_SIGNALFUNC_HPP_
+#define _I2N_SIGNALFUNC_HPP_
+
+#include <vector>
+
+// with pain in the stomach; the following include was added....:
+// (since these includes a lot of #define's... what we usually don't want to have in C++ headers...)
+#include <sys/types.h>
+
+extern "C"
+{
+
+struct siginfo;
+
+}
+
+
+namespace I2n
+{
+namespace SystemTools
+{
+
+
+namespace Detail
+{
+
+/**
+ * base class for internal implementation classes.
+ */
+class SObject
+{
+ public:
+ virtual ~SObject() {}
+}; // eo class SObject
+
+} // eo namespace Detail
+
+/**
+ * @brief representation of system signal.
+ *
+ * This struct also provides constants for the usual system signals; so it is not necessary to include signal.h
+ * for obtaining the constants.
+ *
+ * Due to an appropriate cast operator instances of the class can be used in all places where
+ * a plain signal (i.e. an int) is expected.
+ */
+struct Signal
+{
+ static const int VOID;
+/// @cond
+
+#define SIG(s) static const int s
+ SIG(HUP); SIG(INT); SIG(QUIT); SIG(ILL); SIG(TRAP);
+ SIG(ABRT); SIG(IOT); SIG(BUS); SIG(FPE); SIG(KILL);
+ SIG(USR1); SIG(SEGV); SIG(USR2); SIG(PIPE); SIG(ALRM);
+ SIG(TERM); SIG(STKFLT); SIG(CLD); SIG(CHLD); SIG(CONT); SIG(STOP);
+ SIG(TSTP); SIG(TTIN); SIG(TTOU); SIG(URG); SIG(XCPU);
+ SIG(XFSZ); SIG(VTALRM); SIG(PROF); SIG(WINCH); SIG(POLL);
+ SIG(IO); SIG(PWR); SIG(SYS);
+#undef SIG
+
+/// @endcond
+
+ static int RT(int num=0);
+
+ int Value;
+
+ Signal(int signal) : Value(signal) {}
+
+ operator int () const { return Value; }
+}; // eo struct Signal
+
+
+/**
+ * @brief representation of signal codes.
+ *
+ * This struct provides constants for signal codes; so it is not necessary to include signal.h
+ * for obtaining the constants.
+ *
+ * Due to an appropriate cast operator instances of the class can be used in all places where
+ * a plain signal code (i.e. an int) is expected.
+ */
+struct SignalCode
+{
+
+
+/// @cond
+#define CODE(name) static const int name
+ CODE(USER); CODE(QUEUE); CODE(TIMER); CODE(MESGQ);
+ CODE(ASYNCIO);
+#undef SIGIO
+ CODE(SIGIO);
+/// @endcond
+
+ /**
+ * @brief contains the codes for signal SIGILL
+ */
+ struct ILL
+ {
+ /// @cond
+ CODE(ILLOPC); CODE(ILLOPN); CODE(ILLADR); CODE(ILLTRP);
+ CODE(PRVOPC); CODE(PRVREG); CODE(COPROC); CODE(BADSTK);
+ /// @endcond
+ }; // eo struct ILL;
+
+
+ /**
+ * @brief contains the codes for signal SIGFPE
+ */
+ struct FPE
+ {
+ /// @cond
+ CODE(INTDIV); CODE(INTOVF); CODE(FLTDIV); CODE(FLTOVF);
+ CODE(FLTUND); CODE(FLTRES); CODE(FLTINV); CODE(FLTSUB);
+ /// @endcond
+ }; // eo struct FPE
+
+
+ /**
+ * @brief contains the codes for signal SIGSEGV
+ */
+ struct SEGV
+ {
+ /// @cond
+ CODE(MAPERR); CODE(ACCERR);
+ /// @endcond
+ }; // eo struct SEGV
+
+
+ /**
+ * @brief contains the codes for signal SIGBUS
+ */
+ struct BUS
+ {
+ /// @cond
+ CODE(ADRALN); CODE(ADRERR); CODE(OBJERR);
+ /// @endcond
+ }; // eo struct BUS
+
+
+ /**
+ * @brief contains the codes for signal SIGTRAP
+ */
+ struct TRAP
+ {
+ /// @cond
+ CODE(BRKPT); CODE(TRACE);
+ /// @endcond
+ }; // eo struct TRAP
+
+
+ /**
+ * @brief contains the codes for signal SIGCHLD
+ */
+ struct CHLD
+ {
+ /// @cond
+ CODE(EXITED); CODE(KILLED); CODE(DUMPED); CODE(TRAPPED);
+ CODE(STOPPED); CODE(CONTINUED);
+ /// @endcond
+ }; // eo struct CHLD
+
+
+ /**
+ * @brief contains the codes for signal SIGPOLL
+ */
+ struct POLL
+ {
+ /// @cond
+ CODE(IN); CODE(OUT); CODE(MSG); CODE(ERR); CODE(PRI); CODE(HUP);
+ /// @endcond
+ }; // eo strcut POLL
+
+#undef CODE
+
+ int TheCode;
+
+ SignalCode(int code) : TheCode(code) {}
+
+ operator int () const { return TheCode; }
+}; // eo SignalCode
+
+
+
+
+/**
+ * @brief helper for blocking a (or some) signal(s) during an operation.
+ *
+ * This class blocks the given signals when constructed and resets the original block mask
+ * when destructed.
+ */
+class ScopedSignalBlocker
+{
+ public:
+ ScopedSignalBlocker(Signal sig);
+ ScopedSignalBlocker(Signal sig1, Signal sig2);
+ ScopedSignalBlocker(Signal sig1, Signal sig2, Signal sig3);
+ ScopedSignalBlocker(const std::vector<Signal>& sigs);
+ virtual ~ScopedSignalBlocker();
+
+ private:
+ Detail::SObject* Implementation;
+
+}; // eo class ScopedSignalBlocker
+
+
+
+
+bool install_signal_handler(
+ Signal sig,
+ void(*handler)(int)
+);
+
+bool install_signal_handler(
+ Signal sig,
+ void(*handler)(int,struct siginfo*,void*)
+);
+
+bool ignore_signal(Signal sig);
+bool install_default_signal_handler(Signal sig);
+
+bool restore_signal_handler(Signal sig);
+
+
+bool send_signal( pid_t pid, Signal signal);
+
+
+} // eo namespace SysTools
+} // eo namespace I2n
+
+#endif