#include <sys/stat.h>
#include <sys/wait.h>
#include <unistd.h>
+#include <limits.h>
#include <fcntl.h>
#include <errno.h>
#include <signal.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();
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));
}
}
::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(int event)
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(int 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_();
}