// Custom includes
#include <sys/types.h>
-#include <signal.h>
#include <sys/wait.h>
#include <unistd.h>
#include <sys/socket.h>
senf::scheduler::FdManager manager;
senf::scheduler::FIFORunner runner;
senf::scheduler::FdDispatcher dispatcher (manager, runner);
+ manager.timeout(1000);
int pid (start_server());
BOOST_REQUIRE( pid );
SENF_CHECK_NO_THROW( dispatcher.add(sock, boost::bind(&callback, sock, _1),
senf::scheduler::FdDispatcher::EV_READ) );
- manager.timeout(1000);
event = 0;
SENF_CHECK_NO_THROW( manager.processOnce() );
SENF_CHECK_NO_THROW( runner.run() );
// Custom includes
#include <signal.h>
-#include <setjmp.h>
#include <map>
#include <queue>
#include <boost/function.hpp>
--- /dev/null
+// $Id$
+//
+// Copyright (C) 2008
+// 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.
+//
+// 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 SignalDispatcher non-inline non-template implementation */
+
+#include "SignalDispatcher.hh"
+//#include "SignalDispatcher.ih"
+
+// Custom includes
+#include "../Utils/senfassert.hh"
+
+//#include "SignalDispatcher.mpp"
+#define prefix_
+///////////////////////////////cc.p////////////////////////////////////////
+
+senf::scheduler::SignalDispatcher * senf::scheduler::SignalDispatcher::instance_ = 0;
+
+prefix_ senf::scheduler::SignalDispatcher::SignalDispatcher(FdManager & manager,
+ FIFORunner & runner)
+ : manager_ (manager), runner_ (runner), blocked_ (true)
+{
+ SENF_ASSERT( !instance_ );
+ if (pipe(sigPipe_) <0)
+ throw SystemException("pipe()");
+ sigemptyset(&sigSet_);
+ instance_ = this;
+ manager_.set(sigPipe_[0], FdManager::EV_READ, this);
+}
+
+prefix_ senf::scheduler::SignalDispatcher::~SignalDispatcher()
+{
+ sigprocmask(SIG_UNBLOCK, & sigSet_, 0);
+ for (HandlerMap::iterator i (handlers_.begin()); i != handlers_.end(); ++i) {
+ ::signal(i->first, SIG_DFL);
+ runner_.dequeue(&i->second);
+ }
+ manager_.remove(sigPipe_[0]);
+ close(sigPipe_[0]);
+ close(sigPipe_[1]);
+ instance_ = 0;
+}
+
+prefix_ void senf::scheduler::SignalDispatcher::add(int signal, Callback const & cb)
+{
+ HandlerMap::iterator i (handlers_.find(signal));
+ if (i != handlers_.end()) {
+ i->second.cb = cb;
+ return;
+ }
+
+ i = handlers_.insert(std::make_pair(signal, SignalEvent(cb))).first;
+ sigaddset(&sigSet_, signal);
+ runner_.enqueue(&i->second);
+
+ sigset_t sig;
+ sigemptyset(&sig);
+ sigaddset(&sig, signal);
+ sigprocmask(blocked_ ? SIG_BLOCK : SIG_UNBLOCK, &sig, 0);
+
+ // Need to re-register all handlers to update sa_mask
+ for (HandlerMap::iterator j (handlers_.begin()); i != handlers_.end(); ++i) {
+ struct sigaction act;
+ act.sa_sigaction = &sigHandler;
+ act.sa_mask = sigSet_;
+ act.sa_flags = SA_SIGINFO | SA_RESTART;
+ if (j->first == SIGCLD)
+ act.sa_flags |= SA_NOCLDSTOP;
+ if (sigaction(j->first, &act, 0) < 0)
+ throw SystemException("sigaction()");
+ }
+}
+
+prefix_ void senf::scheduler::SignalDispatcher::remove(int signal)
+{
+ ::signal(signal, SIG_DFL);
+ sigset_t sig;
+ sigemptyset(&sig);
+ sigaddset(&sig, signal);
+ sigprocmask(SIG_UNBLOCK, &sig, 0);
+}
+
+prefix_ void senf::scheduler::SignalDispatcher::signal(int events)
+{
+ siginfo_t info;
+ if (read(sigPipe_[0], &info, sizeof(info)) < int(sizeof(info)))
+ return;
+ HandlerMap::iterator i (handlers_.find(info.si_signo));
+ if (i == handlers_.end())
+ return;
+ i->second.siginfo = info;
+ i->second.runnable = true;
+}
+
+prefix_ void senf::scheduler::SignalDispatcher::sigHandler(int signal, ::siginfo_t * siginfo,
+ void *)
+{
+ SENF_ASSERT( instance_ );
+ // The manpage says, si_signo is unused in linux so we set it here
+ siginfo->si_signo = signal;
+ // We can't do much on error anyway so we ignore errors here
+ write(instance_->sigPipe_[1], siginfo, sizeof(*siginfo));
+}
+
+///////////////////////////////cc.e////////////////////////////////////////
+#undef prefix_
+//#include "SignalDispatcher.mpp"
+
+\f
+// 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:
--- /dev/null
+// $Id$
+//
+// Copyright (C) 2008
+// 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.
+//
+// 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 SignalDispatcher inline non-template implementation */
+
+//#include "SignalDispatcher.ih"
+
+// Custom includes
+#include <unistd.h>
+
+#define prefix_ inline
+///////////////////////////////cci.p///////////////////////////////////////
+
+prefix_ void senf::scheduler::SignalDispatcher::blockSignals()
+{
+ if (blocked_) return;
+ sigprocmask(SIG_BLOCK, &sigSet_, 0);
+ blocked_ = true;
+}
+
+prefix_ void senf::scheduler::SignalDispatcher::unblockSignals()
+{
+ if (!blocked_) return;
+ sigprocmask(SIG_UNBLOCK, &sigSet_, 0);
+ blocked_ = false;
+}
+
+///////////////////////////////////////////////////////////////////////////
+// senf::scheduler::SignalDispatcher::SignalEvent
+
+prefix_ senf::scheduler::SignalDispatcher::SignalEvent::SignalEvent(Callback cb_)
+ : cb (cb_)
+{}
+
+prefix_ senf::scheduler::SignalDispatcher::SignalEvent::~SignalEvent()
+{}
+
+prefix_ void senf::scheduler::SignalDispatcher::SignalEvent::run()
+{
+ cb(siginfo);
+}
+
+///////////////////////////////cci.e///////////////////////////////////////
+#undef prefix_
+
+\f
+// 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:
--- /dev/null
+// $Id$
+//
+// Copyright (C) 2008
+// 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.
+//
+// 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 SignalDispatcher public header */
+
+#ifndef HH_SignalDispatcher_
+#define HH_SignalDispatcher_ 1
+
+// Custom includes
+#include <signal.h>
+#include <map>
+#include "FdManager.hh"
+#include "FIFORunner.hh"
+
+//#include "SignalDispatcher.mpp"
+///////////////////////////////hh.p////////////////////////////////////////
+
+namespace senf {
+namespace scheduler {
+
+ /** \brief
+ */
+ class SignalDispatcher
+ : public FdManager::Event
+ {
+ public:
+ ///////////////////////////////////////////////////////////////////////////
+ // Types
+
+ typedef boost::function<void (siginfo_t const &)> Callback;
+
+ ///////////////////////////////////////////////////////////////////////////
+ ///\name Structors and default members
+ ///@{
+
+ explicit SignalDispatcher(FdManager & manager, FIFORunner & runner);
+ ~SignalDispatcher();
+
+ ///@}
+ ///////////////////////////////////////////////////////////////////////////
+
+ void add(int signal, Callback const & cb);
+ void remove(int signal);
+
+ void blockSignals();
+ void unblockSignals();
+
+ protected:
+
+ private:
+ struct SignalEvent
+ : public FIFORunner::TaskInfo
+ {
+ explicit SignalEvent(Callback cb_);
+ virtual ~SignalEvent();
+ virtual void run();
+
+ siginfo_t siginfo;
+ Callback cb;
+ };
+
+ virtual void signal(int events);
+ static void sigHandler(int signal, ::siginfo_t * siginfo, void *);
+
+ FdManager & manager_;
+ FIFORunner & runner_;
+
+ typedef std::map<int, SignalEvent> HandlerMap;
+ HandlerMap handlers_;
+
+ int sigPipe_[2];
+
+ bool blocked_;
+ sigset_t sigSet_;
+
+ static SignalDispatcher * instance_;
+ };
+
+
+}}
+
+///////////////////////////////hh.e////////////////////////////////////////
+#include "SignalDispatcher.cci"
+//#include "SignalDispatcher.ct"
+//#include "SignalDispatcher.cti"
+#endif
+
+\f
+// 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:
--- /dev/null
+// $Id$
+//
+// Copyright (C) 2008
+// 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.
+//
+// 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 SignalDispatcher.test unit tests */
+
+//#include "SignalDispatcher.test.hh"
+//#include "SignalDispatcher.test.ih"
+
+// Custom includes
+#include "SignalDispatcher.hh"
+
+#include "../Utils/auto_unit_test.hh"
+#include <boost/test/test_tools.hpp>
+
+#define prefix_
+///////////////////////////////cc.p////////////////////////////////////////
+
+namespace {
+
+ bool called = false;
+ void handler(siginfo_t const &)
+ {
+ called = true;
+ }
+}
+
+BOOST_AUTO_UNIT_TEST(signalDispatcher)
+{
+ senf::scheduler::FdManager manager;
+ senf::scheduler::FIFORunner runner;
+ senf::scheduler::SignalDispatcher dispatcher (manager, runner);
+ manager.timeout(1000);
+
+ SENF_CHECK_NO_THROW( dispatcher.add(SIGUSR1, &handler) );
+ BOOST_CHECK( ! called );
+ ::kill(::getpid(), SIGUSR1);
+ sleep(1);
+ SENF_CHECK_NO_THROW( dispatcher.unblockSignals() );
+ SENF_CHECK_NO_THROW( manager.processOnce() );
+ SENF_CHECK_NO_THROW( dispatcher.blockSignals() );
+ SENF_CHECK_NO_THROW( runner.run() );
+ BOOST_CHECK( called );
+
+ SENF_CHECK_NO_THROW( dispatcher.remove(SIGUSR1) );
+}
+
+///////////////////////////////cc.e////////////////////////////////////////
+#undef prefix_
+
+\f
+// 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: