#include <sys/stat.h>
#include <sys/wait.h>
#include <unistd.h>
+#include <limits.h>
#include <fcntl.h>
#include <errno.h>
#include <signal.h>
#include "../Exception.hh"
#include "../membind.hh"
#include "../Backtrace.hh"
+#include "../signalnames.hh"
// #define __USE_GNU
#include <ucontext.h>
return argc_;
}
-prefix_ char ** senf::Daemon::argv()
+prefix_ char const ** senf::Daemon::argv()
{
return argv_;
}
prefix_ void senf::Daemon::removeDaemonArgs()
{
- char ** last (std::remove_if(argv_+1, argv_+argc_, IsDaemonOpt()));
+ char const ** last (std::remove_if(argv_+1, argv_+argc_, IsDaemonOpt()));
*last = 0;
argc_ = last - argv_;
}
throw DaemonExitException(code);
}
-prefix_ int senf::Daemon::start(int argc, char ** argv)
+prefix_ int senf::Daemon::start(int argc, char const ** argv)
{
argc_ = argc;
argv_ = argv;
::sigemptyset(&cldsig);
LIBC_CALL( ::sigaddset, (&cldsig, SIGCHLD) );
LIBC_CALL( ::sigprocmask, (SIG_BLOCK, &cldsig, &oldsig) );
+
+ if (! senf::scheduler::empty() )
+ std::cerr <<
+ "\n"
+ "*** WARNING ***\n"
+ "Scheduler not empty before fork(). THIS MUST NOT HAPPEN.\n"
+ "The scheduler will be reinitialized by the fork() and lose all registrations.\n"
+ "*** WARNING ***\n"
+ "\n";
LIBC_CALL_RV( pid, ::fork, () );
LIBC_CALL( ::close, (cerrpipe[1]) );
LIBC_CALL( ::setsid, () );
LIBC_CALL( ::sigprocmask, (SIG_SETMASK, &oldsig, 0) );
+
+ senf::scheduler::restart();
return;
}
LIBC_CALL( ::close, (coutpipe[1]) );
LIBC_CALL( ::close, (cerrpipe[1]) );
+ senf::scheduler::restart();
+
detail::DaemonWatcher watcher (pid, coutpipe[0], cerrpipe[0], stdout_, stderr_);
watcher.run();
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<ucontext_t*>(arg);
- std::cerr << "\n" << "Signal " << sig;
- if (unsigned(sig) < sizeof(signames) / sizeof(signames[0]))
- std::cerr << " (" << signames[unsigned(sig)] << ")";
- std::cerr << " received\n";
+ std::cerr << "\n" << "Signal " << senf::signalName(sig) << '(' << sig << ')'
+ << " received\n";
if (sig == SIGSEGV)
std::cerr << "Invalid memory access at " << info->si_addr << "\n";
::sigaction(SIGHUP, &sa, NULL);
+ sa.sa_handler = SIG_IGN;
+ ::sigaction(SIGPIPE, &sa, NULL);
+
#ifdef SENF_DEBUG
sa.sa_sigaction = &fatalSignalsHandler;
sa.sa_flags = SA_RESTART | SA_SIGINFO;
int stdout, int stderr)
: childPid_(pid), coutpipe_(coutpipe), cerrpipe_(cerrpipe), stdout_(stdout),
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))
{
prefix_ void senf::detail::DaemonWatcher::run()
{
- Scheduler::instance().registerSignal(SIGCHLD, senf::membind(&DaemonWatcher::sigChld, this));
- Scheduler::instance().process();
+ scheduler::process();
}
////////////////////////////////////////
if (coutpipe_ == -1 && cerrpipe_ == -1) {
if (sigChld_)
childDied(); // does not return
- if (::kill(childPid_, SIGUSR1) < 0)
- if (errno != ESRCH) SENF_THROW_SYSTEM_EXCEPTION("::kill()");
- Scheduler::instance().timeout(
- Scheduler::instance().eventTime() + ClockService::seconds(1),
- senf::membind(&DaemonWatcher::childOk, this));
+ if (::kill(childPid_, SIGUSR1) < 0 && errno != ESRCH)
+ SENF_THROW_SYSTEM_EXCEPTION("::kill()");
+ timer_.timeout(scheduler::eventTime() + ClockService::seconds(1));
}
}
-prefix_ void senf::detail::DaemonWatcher::sigChld()
+prefix_ void senf::detail::DaemonWatcher::sigChld(siginfo_t const &)
{
sigChld_ = true;
if (coutpipe_ == -1 && cerrpipe_ == -1)
::signal(WTERMSIG(status),SIG_DFL);
::kill(::getpid(), WTERMSIG(status));
// should not be reached
- ::_exit(1);
+ ::_exit(126);
}
if (WEXITSTATUS(status) == 0)
- ::_exit(1);
+ ::_exit(127);
::_exit(WEXITSTATUS(status));
}
prefix_ void senf::detail::DaemonWatcher::childOk()
{
- Scheduler::instance().terminate();
+ scheduler::terminate();
}
///////////////////////////////////////////////////////////////////////////
// senf::detail::DaemonWatcher::Forwarder
prefix_ senf::detail::DaemonWatcher::Forwarder::Forwarder(int src, Callback cb)
- : src_(src), cb_(cb)
-{
- Scheduler::instance().add(src_, senf::membind(&Forwarder::readData, this),
- Scheduler::EV_READ);
-}
+ : src_(src), cb_(cb),
+ readevent_("senf::detail::DaemonWatcher::Forwarder::readevent", senf::membind(&Forwarder::readData, this),
+ src_, scheduler::FdEvent::EV_READ)
+{}
prefix_ senf::detail::DaemonWatcher::Forwarder::~Forwarder()
{
- if (src_ != -1)
- Scheduler::instance().remove(src_);
-
- for (Targets::iterator i (targets_.begin()); i != targets_.end(); ++i)
- if (i->offset >= buffer_.size())
- Scheduler::instance().remove(i->fd);
+ targets_.clear_and_destroy(DestroyDelete());
}
prefix_ void senf::detail::DaemonWatcher::Forwarder::addTarget(int fd)
{
- Target target = { fd, 0 };
- targets_.push_back(target);
+ targets_.push_back(*(new Target(*this, fd)));
}
-prefix_ void senf::detail::DaemonWatcher::Forwarder::readData(Scheduler::EventId event)
+prefix_ void senf::detail::DaemonWatcher::Forwarder::readData(int event)
{
char buf[1024];
int n (0);
while (1) {
n = ::read(src_,buf,1024);
if (n<0) {
- if (errno != EINTR) SENF_THROW_SYSTEM_EXCEPTION("::read()");
- } else
+ if (errno != EINTR)
+ SENF_THROW_SYSTEM_EXCEPTION("::read()");
+ }
+ else
break;
}
if (n == 0) {
- // Hangup
- Scheduler::instance().remove(src_);
if (buffer_.empty())
cb_();
src_ = -1;
+ readevent_.disable();
return;
}
for (Targets::iterator i (targets_.begin()); i != targets_.end(); ++i)
if (i->offset >= buffer_.size())
- Scheduler::instance().add( i->fd,
- boost::bind(&Forwarder::writeData, this, _1, i),
- Scheduler::EV_WRITE );
+ i->writeevent.enable();
buffer_.insert(buffer_.end(), buf, buf+n);
}
-prefix_ void senf::detail::DaemonWatcher::Forwarder::writeData(Scheduler::EventId event,
- Targets::iterator target)
+prefix_ void senf::detail::DaemonWatcher::Forwarder::writeData(int event, Target * target)
{
- if (event != Scheduler::EV_WRITE) {
+ if (event != scheduler::FdEvent::EV_WRITE) {
// Broken pipe while writing data ? Not much, we can do here, we just drop the data
- Scheduler::instance().remove(target->fd);
- targets_.erase(target);
+ targets_.erase_and_destroy(Targets::current(*target),DestroyDelete());
if (targets_.empty() && src_ == -1)
cb_();
return;
i->offset -= n;
if (target->offset >= buffer_.size())
- Scheduler::instance().remove(target->fd);
+ target->writeevent.disable();
if (src_ == -1 && (buffer_.empty() || targets_.empty()))
cb_();
}