senf::console::Server::start(senf::INet4SocketAddress const & address)
{
senf::TCPv4ServerSocketHandle handle (address);
- senf::console::Server::start(handle);
+ Server & server (senf::console::Server::start(handle));
SENF_LOG((Server::SENFLogArea)(log::NOTICE)(
"Console server started at " << address ));
- return *instance_;
+ return server;
}
prefix_ senf::console::Server &
senf::console::Server::start(senf::INet6SocketAddress const & address)
{
senf::TCPv6ServerSocketHandle handle (address);
- senf::console::Server::start(handle);
+ Server & server (senf::console::Server::start(handle));
SENF_LOG((Server::SENFLogArea)(log::NOTICE)(
"Console server started at " << address ));
- return *instance_;
+ return server;
}
-boost::scoped_ptr<senf::console::Server> senf::console::Server::instance_;
+prefix_ boost::scoped_ptr<senf::console::Server> & senf::console::Server::instancePtr()
+{
+ // We cannot make 'instance' a global or class-static variable, since it will then be destructed
+ // at an unknown time which may fail if the scheduler or the file-handle pool allocators have
+ // already been destructed.
+ static boost::scoped_ptr<senf::console::Server> instance;
+ return instance;
+}
-prefix_ void senf::console::Server::start(ServerHandle handle)
+prefix_ senf::console::Server & senf::console::Server::start(ServerHandle handle)
{
- SENF_ASSERT( ! instance_ );
- instance_.reset(new Server(handle));
+ // Uah .... ensure the scheduler is created before the instance pointer so it get's destructed
+ // AFTER it.
+ (void) senf::Scheduler::instance();
+ SENF_ASSERT( ! instancePtr() );
+ instancePtr().reset(new Server(handle));
+ return * instancePtr();
}
prefix_ senf::console::Server::Server(ServerHandle handle)
prefix_ void senf::console::Server::newClient(Scheduler::EventId event)
{
ServerHandle::ClientSocketHandle client (handle_.accept());
- boost::intrusive_ptr<Client> p (new Client(client, name_));
+ boost::intrusive_ptr<Client> p (new Client(*this, client, name_));
clients_.insert( p );
SENF_LOG(( "Registered new client " << p.get() ));
}
///////////////////////////////////////////////////////////////////////////
// senf::console::Client
-prefix_ senf::console::Client::Client(ClientHandle handle, std::string const & name)
- : out_t(handle), senf::log::IOStreamTarget(out_t::member),
- handle_ (handle), name_ (name), promptLen_(0)
+prefix_ senf::console::Client::Client(Server & server, ClientHandle handle,
+ std::string const & name)
+ : out_t(handle), senf::log::IOStreamTarget(out_t::member), server_ (server),
+ handle_ (handle), name_ (name), promptLen_(0)
{
showPrompt();
ReadHelper<ClientHandle>::dispatch( handle_, 16384u, ReadUntil("\n"),
prefix_ void senf::console::Client::stopClient()
{
// THIS COMMITS SUICIDE. THE INSTANCE IS GONE AFTER removeClient RETURNS
- Server::instance_->removeClient(*this);
+ server_.removeClient(*this);
}
prefix_ void senf::console::Client::clientData(ReadHelper<ClientHandle>::ptr helper)
lastCommand_ = data;
try {
- if (! parser_.parse(data, boost::bind<void>(boost::ref(executor_), _1,
- boost::ref(out_t::member))))
+ if (! parser_.parse(data, boost::bind<void>( boost::ref(executor_),
+ boost::ref(out_t::member),
+ _1 )) )
out_t::member << "syntax error" << std::endl;
}
catch (Executor::ExitException &) {