From 8cabc8bcdcd22e8726734f1a18f23ed7d9c19e9f Mon Sep 17 00:00:00 2001 From: Tim Moore Date: Tue, 8 Dec 2009 23:17:47 +0100 Subject: grapher: start of a dialog for displaying active stap processes The names of active scripts are displayed in a list; mock buttons suggest being able to stop and restart them. * grapher/processwindow.glade: new file * grapher/Makefile.am: add processwindow.glade to installed files * grapher/StapParser.hxx (StapProcess): new class (StapParser): factor out members that are now in StapProcess (ioCallback): Use the new childDied signal instead of aborting the whole grapher when a child dies. * grapher/grapher.cxx (ProcModelColumns, ProcWindow): classes for displaying stap process window. (GrapherWindow::on_menu_proc_window): new function --- grapher/grapher.cxx | 156 ++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 126 insertions(+), 30 deletions(-) (limited to 'grapher/grapher.cxx') diff --git a/grapher/grapher.cxx b/grapher/grapher.cxx index 4769877f..2a9a617b 100644 --- a/grapher/grapher.cxx +++ b/grapher/grapher.cxx @@ -39,6 +39,7 @@ #include using namespace std; +using namespace tr1; using namespace systemtap; @@ -159,22 +160,33 @@ public: } int launch(); void cleanUp(); - tr1::shared_ptr makeStapParser() + shared_ptr makeStapParser() { - tr1::shared_ptr result(new StapParser(_win)); - _parsers.push_back(ParserInstance(-1, result)); + shared_ptr result(new StapParser); + _parsers.push_back(result); return result; } +private: + struct pidPred + { + pidPred(pid_t pid_) : pid(pid_) {} + bool operator()(const shared_ptr& parser) const + { + return parser->getPid() == pid; + } + pid_t pid; + }; +public: pid_t reap() { + using namespace boost; pid_t pid = ChildDeathReader::reap(); if (pid < 0) return pid; ParserList::iterator itr - = find_if(_parsers.begin(), _parsers.end(), - boost::bind(&ParserInstance::childPid, _1) == pid); + = find_if(_parsers.begin(), _parsers.end(), pidPred(pid)); if (itr != _parsers.end()) - itr->childPid = -1; + (*itr)->setProcess(tr1::shared_ptr()); return pid; } void killAll() @@ -183,10 +195,12 @@ public: itr != end; ++itr) { - if (itr->childPid >= 0) - kill(itr->childPid, SIGTERM); + if ((*itr)->getPid() >= 0) + kill((*itr)->getPid(), SIGTERM); } } + typedef vector > ParserList; + ParserList _parsers; protected: char** _argv; string _stapArgs; @@ -196,18 +210,6 @@ protected: ChildDeathReader::Callback* _deathCallback; Gtk::Window* _win; GraphWidget* _widget; - struct ParserInstance - { - ParserInstance() : childPid(-1) {} - ParserInstance(int childPid_, tr1::shared_ptr stapParser_) - : childPid(childPid_), stapParser(stapParser_) - { - } - pid_t childPid; - tr1::shared_ptr stapParser; - }; - typedef vector ParserList; - ParserList _parsers; }; int StapLauncher::launch() @@ -274,8 +276,18 @@ int StapLauncher::launch() } _exit(1); } - tr1::shared_ptr sp(new StapParser(_win)); - _parsers.push_back(ParserInstance(childPid, sp)); + tr1::shared_ptr sp(new StapParser); + shared_ptr proc(new StapProcess(childPid)); + if (_argv) + proc->argv = _argv; + else + { + proc->stapArgs = _stapArgs; + proc->script = _script; + proc->scriptArgs = _scriptArgs; + } + sp->setProcess(proc); + _parsers.push_back(sp); sp->setErrFd(pipefd[2]); sp->setInFd(pipefd[0]); Glib::signal_io().connect(sigc::mem_fun(sp.get(), @@ -305,21 +317,22 @@ void StapLauncher::cleanUp() itr != end; ++itr) { - if (itr->childPid > 0) - kill(itr->childPid, SIGTERM); + pid_t childPid = (*itr)->getPid(); + if (childPid > 0) + kill(childPid, SIGTERM); int status; pid_t killedPid = -1; if ((killedPid = wait(&status)) == -1) { std::perror("wait"); } - else if (killedPid != itr->childPid) + else if (killedPid != childPid) { std::cerr << "wait: killed Pid " << killedPid << " != child Pid " - << itr->childPid << "\n"; + << childPid << "\n"; } else if (_deathCallback) - _deathCallback->childDied(itr->childPid); + _deathCallback->childDied(childPid); } } @@ -338,6 +351,58 @@ private: Gtk::Entry* _scriptArgEntry; }; +class ProcModelColumns : public Gtk::TreeModelColumnRecord +{ +public: + ProcModelColumns() + { + add(_scriptName); + add(_proc); + } + Gtk::TreeModelColumn _scriptName; + Gtk::TreeModelColumn > _proc; +}; + +class ProcWindow +{ +public: + ProcWindow(); + ProcModelColumns _modelColumns; + Glib::RefPtr _xml; + Gtk::Window* _window; + Gtk::TreeView* _dataTreeView; + Glib::RefPtr _listStore; + void onClose(); +}; + +ProcWindow::ProcWindow() +{ + try + { + _xml = Gnome::Glade::Xml::create(PKGDATADIR "/processwindow.glade"); + _xml->get_widget("window1", _window); + _xml->get_widget("treeview1", _dataTreeView); + + } + catch (const Gnome::Glade::XmlError& ex ) + { + std::cerr << ex.what() << std::endl; + throw; + } + _listStore = Gtk::ListStore::create(_modelColumns); + _dataTreeView->set_model(_listStore); + _dataTreeView->append_column("Script", _modelColumns._scriptName); + Gtk::Button* button = 0; + _xml->get_widget("button5", button); + button->signal_clicked().connect(sigc::mem_fun(*this, &ProcWindow::onClose), + false); +} + +void ProcWindow::onClose() +{ + _window->hide(); +} + class GrapherWindow : public Gtk::Window, public ChildDeathReader::Callback { public: @@ -355,25 +420,28 @@ public: protected: virtual void on_menu_file_quit(); virtual void on_menu_script_start(); + virtual void on_menu_proc_window(); void addGraph(); // menu support Glib::RefPtr m_refUIManager; Glib::RefPtr m_refActionGroup; GraphicalStapLauncher* _graphicalLauncher; - + shared_ptr _procWindow; }; + GrapherWindow::GrapherWindow() + : _procWindow(new ProcWindow) { set_title("systemtap grapher"); add(m_Box); - + //Create actions for menus and toolbars: m_refActionGroup = Gtk::ActionGroup::create(); //File menu: m_refActionGroup->add(Gtk::Action::create("FileMenu", "File")); - m_refActionGroup->add(Gtk::Action::create("StartScript", "Start script"), + m_refActionGroup->add(Gtk::Action::create("StartScript", "Start script..."), sigc::mem_fun(*this, &GrapherWindow::on_menu_script_start)); m_refActionGroup->add(Gtk::Action::create("AddGraph", "Add graph"), @@ -381,6 +449,12 @@ GrapherWindow::GrapherWindow() m_refActionGroup->add(Gtk::Action::create("FileQuit", Gtk::Stock::QUIT), sigc::mem_fun(*this, &GrapherWindow::on_menu_file_quit)); + // Window menu + m_refActionGroup->add(Gtk::Action::create("WindowMenu", "Window")); + m_refActionGroup->add(Gtk::Action::create("ProcessWindow", + "Stap processes..."), + sigc::mem_fun(*this, + &GrapherWindow::on_menu_proc_window)); m_refUIManager = Gtk::UIManager::create(); m_refUIManager->insert_action_group(m_refActionGroup); @@ -394,6 +468,9 @@ GrapherWindow::GrapherWindow() " " " " " " + " " + " " + " " " " ""; try @@ -425,6 +502,25 @@ void GrapherWindow::on_menu_script_start() _graphicalLauncher->runDialog(); } + +void GrapherWindow::on_menu_proc_window() +{ + _procWindow->_listStore->clear(); + for (StapLauncher::ParserList::iterator spitr + = _graphicalLauncher->_parsers.begin(), + end = _graphicalLauncher->_parsers.end(); + spitr != end; + ++spitr) + { + shared_ptr sp = (*spitr)->getProcess(); + Gtk::TreeModel::iterator litr = _procWindow->_listStore->append(); + Gtk::TreeModel::Row row = *litr; + if (sp) + row[_procWindow->_modelColumns._scriptName] = sp->script; + } + _procWindow->_window->show(); +} + void GrapherWindow::childDied(int pid) { hide(); -- cgit