detail::FdDispatcher::FdSet::iterator const i_end (detail::FdDispatcher::instance().fds_.end());
bool all ((events & (EV_ERR | EV_HUP)) && ! (events & (EV_READ | EV_PRIO | EV_WRITE)));
for (; i != i_end && fd_ == i->fd_; ++i) {
- i->signaledEvents_ = events;
+ i->signaledEvents_ = events & (EV_ERR | EV_HUP | i->events_);
if (i->events_ & events || all)
i->setRunnable();
}
template <class Signature>
typename detail::ParsedCommandTraits<Signature>::Attributor
- senf_console_add_node(DirectoryNode & node, std::string const & name, boost::function<Signature> fn, int);
+ senf_console_add_node(DirectoryNode & node, std::string const & name,
+ boost::function<Signature> fn, int);
template <class Owner, class Function>
typename detail::ParsedCommandTraits<Function>::Attributor
#include "../../Utils/membind.hh"
#include "../../Utils/Logger/SenfLog.hh"
#include "LineEditor.hh"
+#include "ScopedDirectory.hh"
+#include "Sysdir.hh"
+#include "ParsedCommand.hh"
//#include "Server.mpp"
#define prefix_
_1 ));
}
catch (Executor::ExitException &) {
- // This generates an EOF condition on the Handle. This EOF condition is expected
- // to be handled gracefully by the ClientReader. We cannot call stop() here, since we
- // are called from the client reader callback and that will continue executing even if we
- // call stop here ...
+ // This generates an EOF condition on the Handle. This EOF condition is expected to be
+ // handled gracefully by the ClientReader. We cannot call stop() here, since we are called
+ // from the client reader callback and that will continue executing after stop() has been
+ // called. stop() however will delete *this instance ... BANG ...
handle_.facet<senf::TCPSocketProtocol>().shutdown(senf::TCPSocketProtocol::ShutRD);
}
catch (std::exception & ex) {
std::string msg (ex.what());
std::string::size_type i (msg.find("-- \n"));
- if (i != std::string::npos)
+ if (i != std::string::npos) {
+ backtrace_ = msg.substr(0,i);
msg = msg.substr(i+4);
+ } else
+ backtrace_.clear();
stream() << msg << std::endl;
}
catch (...) {
return os << *client;
}
+///////////////////////////////////////////////////////////////////////////
+// senf::console::Client::SysBacktrace
+
+prefix_ senf::console::Client::SysBacktrace::SysBacktrace()
+{
+ sysdir().node().add("backtrace", &SysBacktrace::backtrace)
+ .doc("Display the backtrace of the last error / exception in this console");
+}
+
+prefix_ void senf::console::Client::SysBacktrace::backtrace(std::ostream & os)
+{
+ Client & client (Client::get(os));
+ if (client.backtrace().empty())
+ os << "(no backtrace)";
+ else
+ os << client.backtrace();
+}
+
+senf::console::Client::SysBacktrace senf::console::Client::SysBacktrace::instance_;
+
///////////////////////////////cc.e////////////////////////////////////////
#undef prefix_
//#include "Server.mpp"
reader_->write(data);
}
+prefix_ std::string const & senf::console::Client::backtrace()
+ const
+{
+ return backtrace_;
+}
+
prefix_ senf::console::Client & senf::console::Client::get(std::ostream & os)
{
return dynamic_cast<detail::NonblockingSocketOStream&>(os)->client();
DirectoryNode & cwd() const;
Server::Mode mode() const;
void write(std::string const & data) const;
+ std::string const & backtrace() const;
static Client & get(std::ostream & os);
void setInteractive();
void setNoninteractive();
-
+
size_t handleInput(std::string input, bool incremental = false);
virtual void v_write(senf::log::time_type timestamp, std::string const & stream,
std::string const & area, unsigned level,
std::string lastCommand_;
boost::scoped_ptr<detail::ClientReader> reader_;
Server::Mode mode_;
+ std::string backtrace_;
friend class Server;
friend class detail::ClientReader;
friend class detail::NonblockingSocketSink;
+
+ class SysBacktrace
+ {
+ SysBacktrace();
+ static void backtrace(std::ostream & os);
+ static SysBacktrace instance_;
+ };
+
};
/** \brief Output Console Client instance as it's string representation