summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTim Moore <timoore@redhat.com>2009-12-11 14:03:47 +0100
committerTim Moore <timoore@redhat.com>2009-12-11 14:16:26 +0100
commite47f92ea31a605802c59541ca325ffd567c45ca4 (patch)
tree8a10b369ed8836cf9c87cadc45050e67d768ca09
parente83324285bb277300f5c91ee1c2a39bf04df502d (diff)
downloadsystemtap-steved-e47f92ea31a605802c59541ca325ffd567c45ca4.tar.gz
systemtap-steved-e47f92ea31a605802c59541ca325ffd567c45ca4.tar.xz
systemtap-steved-e47f92ea31a605802c59541ca325ffd567c45ca4.zip
grapher: implement restarting a stap process
* grapher/StapParser.cxx (StapParser::disconnect): new function * grapher/StapParser.hxx (StapProcess::StapProcess): initialize argv to 0 * grapher/grapher.cxx (StapLauncher::setArgs): Set argv to 0 (StapLauncher launch, launchUsingParser): Refactor launch(), extracting function a that (re)launches a stap process using an existing parser. (StapLauncher::onChildDied): call disconnect() on dead parser. (GrapherWindow::_graphicalLauncher, setGraphicalLauncher): delete member, replacing with... (graphicalLauncher): new variable (ProcModelColumns): Store parser object in the list model instead of just a StapProcess object. (ProcWindow::onRestart): new function (ProcWindow::refresh): Preserve the list selection when the process list is refreshed. (ProcWindow::onSelectionChanged): Manage the restart button's state.
-rw-r--r--grapher/StapParser.cxx18
-rw-r--r--grapher/StapParser.hxx3
-rw-r--r--grapher/grapher.cxx155
3 files changed, 128 insertions, 48 deletions
diff --git a/grapher/StapParser.cxx b/grapher/StapParser.cxx
index 2513680b..2595e8cc 100644
--- a/grapher/StapParser.cxx
+++ b/grapher/StapParser.cxx
@@ -288,4 +288,22 @@ vector<string> commaSplit(const boost::sub_range<Glib::ustring>& range)
_inFd, inCond);
}
+
+ void StapParser::disconnect()
+ {
+ if (_ioConnection.connected())
+ _ioConnection.disconnect();
+ if (_errIoConnection.connected())
+ _errIoConnection.disconnect();
+ if (_inFd >= 0)
+ {
+ close(_inFd);
+ _inFd = -1;
+ }
+ if (_errFd >= 0)
+ {
+ close(_errFd);
+ _errFd = -1;
+ }
+ }
}
diff --git a/grapher/StapParser.hxx b/grapher/StapParser.hxx
index 24e84fc9..169533b6 100644
--- a/grapher/StapParser.hxx
+++ b/grapher/StapParser.hxx
@@ -18,7 +18,7 @@ namespace systemtap
// arguments and script for a stap process
struct StapProcess
{
- StapProcess(pid_t pid_ = -1) : pid(pid_) {}
+ StapProcess(pid_t pid_ = -1) : argv(0), pid(pid_) {}
std::string stapArgs;
std::string script;
std::string scriptArgs;
@@ -67,6 +67,7 @@ namespace systemtap
_process = process;
}
void initIo(int inFd, int errFd, bool catchHUP);
+ void disconnect();
};
sigc::signal<void, pid_t>& childDiedSignal();
diff --git a/grapher/grapher.cxx b/grapher/grapher.cxx
index 6dead221..0111184a 100644
--- a/grapher/grapher.cxx
+++ b/grapher/grapher.cxx
@@ -153,6 +153,7 @@ public:
void setArgs(const string& stapArgs, const string& script,
const string& scriptArgs)
{
+ _argv = 0;
_stapArgs = stapArgs;
_script = script;
_scriptArgs = scriptArgs;
@@ -174,6 +175,7 @@ public:
}
int launch();
+ int launchUsingParser(shared_ptr<StapParser> parser);
shared_ptr<StapParser> makeStapParser()
{
shared_ptr<StapParser> result(new StapParser);
@@ -188,6 +190,7 @@ public:
= find_if(parsers.begin(), parsers.end(), PidPred(pid));
if (itr != parsers.end())
{
+ (*itr)->disconnect();
tr1::shared_ptr<StapProcess> sp = (*itr)->getProcess();
if (sp)
{
@@ -218,7 +221,36 @@ protected:
int StapLauncher::launch()
{
- int childPid = -1;
+ tr1::shared_ptr<StapParser> sp(new StapParser);
+ shared_ptr<StapProcess> proc(new StapProcess(-1));
+ if (_argv)
+ proc->argv = _argv;
+ else
+ {
+ proc->stapArgs = _stapArgs;
+ proc->script = _script;
+ proc->scriptArgs = _scriptArgs;
+ }
+ sp->setProcess(proc);
+ pid_t childPid = launchUsingParser(sp);
+ if (childPid >= 0)
+ {
+ parsers.push_back(sp);
+ parserListChangedSignal().emit();
+ }
+ return childPid;
+}
+
+int StapLauncher::launchUsingParser(shared_ptr<StapParser> sp)
+{
+ shared_ptr<StapProcess> proc = sp->getProcess();
+ if (!proc)
+ {
+ cerr << "Can't launch parser with null process structure\n";
+ return -1;
+ }
+
+ proc->pid = -1;
if (signalPipe[0] < 0)
{
if (pipe(&signalPipe[0]) < 0)
@@ -245,11 +277,11 @@ int StapLauncher::launch()
std::perror("pipe");
exit(1);
}
- if ((childPid = fork()) == -1)
+ if ((proc->pid = fork()) == -1)
{
exit(1);
}
- else if (childPid)
+ else if (proc->pid)
{
close(pipefd[1]);
close(pipefd[3]);
@@ -260,41 +292,28 @@ int StapLauncher::launch()
dup2(pipefd[3], STDERR_FILENO);
for_each(&pipefd[0], &pipefd[4], close);
for_each(&signalPipe[0], &signalPipe[2], close);
- if (_argv)
+ if (proc->argv)
{
char argv0[] = "stap";
- char** argvEnd = _argv;
+ char** argvEnd = proc->argv;
for (; *argvEnd; ++argvEnd)
;
- char** realArgv = new char*[argvEnd - _argv + 2];
+ char** realArgv = new char*[argvEnd - proc->argv + 2];
realArgv[0] = argv0;
std::copy(_argv, argvEnd + 1, &realArgv[1]);
execvp("stap", realArgv);
}
else
{
- string argString = "stap" + _stapArgs + " " + _script + " "
- + _scriptArgs;
+ string argString = "stap" + proc->stapArgs + " " + proc->script + " "
+ + proc->scriptArgs;
execl("/bin/sh", "sh", "-c", argString.c_str(),
static_cast<char*>(0));
}
_exit(1);
}
- tr1::shared_ptr<StapParser> sp(new StapParser);
- shared_ptr<StapProcess> 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);
- parserListChangedSignal().emit();
sp->initIo(pipefd[0], pipefd[2], false);
- return childPid;
+ return proc->pid;
}
class GraphicalStapLauncher : public StapLauncher
@@ -312,6 +331,8 @@ private:
Gtk::Entry* _scriptArgEntry;
};
+GraphicalStapLauncher *graphicalLauncher = 0;
+
class ProcModelColumns : public Gtk::TreeModelColumnRecord
{
public:
@@ -319,11 +340,11 @@ public:
{
add(_iconName);
add(_scriptName);
- add(_proc);
+ add(_parser);
}
Gtk::TreeModelColumn<Glib::ustring> _iconName;
Gtk::TreeModelColumn<Glib::ustring> _scriptName;
- Gtk::TreeModelColumn<shared_ptr<StapProcess> > _proc;
+ Gtk::TreeModelColumn<shared_ptr<StapParser> > _parser;
};
// This should probably be a Gtk window, with the appropriate glade magic
@@ -347,6 +368,7 @@ public:
void onParserListChanged();
void onSelectionChanged();
void onKill();
+ void onRestart();
private:
bool _open;
void refresh();
@@ -385,6 +407,8 @@ ProcWindow::ProcWindow()
.connect(sigc::mem_fun(*this, &ProcWindow::onKill), false);
_killButton->set_sensitive(false);
_xml->get_widget("button2", _restartButton);
+ _restartButton->signal_clicked()
+ .connect(sigc::mem_fun(*this, &ProcWindow::onRestart), false);
_restartButton->set_sensitive(false);
parserListChangedSignal()
.connect(sigc::mem_fun(*this, &ProcWindow::onParserListChanged));
@@ -416,25 +440,53 @@ void ProcWindow::hide()
void ProcWindow::refresh()
{
+ // If a process is already selected, try to leave it selected after
+ // the list is reconstructed.
+ shared_ptr<StapParser> selectedParser;
+ {
+ Gtk::TreeModel::iterator itr = _listSelection->get_selected();
+ if (itr)
+ {
+ Gtk::TreeModel::Row row = *itr;
+ selectedParser = row[_modelColumns._parser];
+ }
+ }
_listStore->clear();
for (ParserList::iterator spitr = parsers.begin(), end = parsers.end();
spitr != end;
++spitr)
{
- shared_ptr<StapProcess> sp = (*spitr)->getProcess();
+ shared_ptr<StapParser> parser = *spitr;
+ shared_ptr<StapProcess> sp = parser->getProcess();
Gtk::TreeModel::iterator litr = _listStore->append();
Gtk::TreeModel::Row row = *litr;
if (sp)
{
row[_modelColumns._iconName] = sp->pid >= 0 ? "gtk-yes" : "gtk-no";
row[_modelColumns._scriptName] = sp->script;
- row[_modelColumns._proc] = sp;
}
else
{
row[_modelColumns._iconName] = "gtk-yes";
row[_modelColumns._scriptName] = "standard input";
}
+ row[_modelColumns._parser] = parser;
+ }
+ if (selectedParser)
+ {
+ Gtk::TreeModel::Children children = _listStore->children();
+ for (Gtk::TreeModel::Children::const_iterator itr = children.begin(),
+ end = children.end();
+ itr != end;
+ ++itr)
+ {
+ Gtk::TreeModel::Row row = *itr;
+ if (row[_modelColumns._parser] == selectedParser)
+ {
+ _listSelection->select(row);
+ break;
+ }
+ }
}
}
@@ -450,24 +502,26 @@ void ProcWindow::onParserListChanged()
void ProcWindow::onSelectionChanged()
{
Gtk::TreeModel::iterator itr = _listSelection->get_selected();
+ shared_ptr<StapParser> parser;
shared_ptr<StapProcess> proc;
if (itr)
{
Gtk::TreeModel::Row row = *itr;
- proc = row[_modelColumns._proc];
+ parser = row[_modelColumns._parser];
+ proc = parser->getProcess();
}
if (proc)
{
- if (proc->pid >= 0)
- _killButton->set_sensitive(true);
- else
- _killButton->set_sensitive(false);
+ bool procRunning = proc->pid >= 0;
+ _killButton->set_sensitive(procRunning);
+ _restartButton->set_sensitive(!procRunning);
_stapArgsLabel->set_text(proc->stapArgs);
_scriptArgsLabel->set_text(proc->scriptArgs);
}
else
{
_killButton->set_sensitive(false);
+ _restartButton->set_sensitive(false);
_stapArgsLabel->set_text("");
_scriptArgsLabel->set_text("");
}
@@ -479,11 +533,26 @@ void ProcWindow::onKill()
if (!itr)
return;
Gtk::TreeModel::Row row = *itr;
- shared_ptr<StapProcess> proc = row[_modelColumns._proc];
- if (proc->pid >= 0)
+ shared_ptr<StapParser> parser = row[_modelColumns._parser];
+ shared_ptr<StapProcess> proc = parser->getProcess();
+ if (proc && proc->pid >= 0)
kill(proc->pid, SIGTERM);
}
+void ProcWindow::onRestart()
+{
+ Gtk::TreeModel::iterator itr = _listSelection->get_selected();
+ if (!itr)
+ return;
+ Gtk::TreeModel::Row row = *itr;
+ shared_ptr<StapParser> parser = row[_modelColumns._parser];
+ shared_ptr<StapProcess> proc = parser->getProcess();
+ if (!proc)
+ return;
+ if (graphicalLauncher->launchUsingParser(parser) > 0)
+ parserListChangedSignal().emit();
+}
+
class GrapherWindow : public Gtk::Window
{
public:
@@ -492,11 +561,6 @@ public:
Gtk::VBox m_Box;
Gtk::ScrolledWindow scrolled;
GraphWidget w;
- void setGraphicalLauncher(GraphicalStapLauncher* launcher)
- {
- _graphicalLauncher = launcher;
- }
- GraphicalStapLauncher* getGraphicalLauncher() { return _graphicalLauncher; }
protected:
virtual void on_menu_file_quit();
virtual void on_menu_script_start();
@@ -506,7 +570,6 @@ protected:
// menu support
Glib::RefPtr<Gtk::UIManager> m_refUIManager;
Glib::RefPtr<Gtk::ActionGroup> m_refActionGroup;
- GraphicalStapLauncher* _graphicalLauncher;
shared_ptr<ProcWindow> _procWindow;
bool _quitting;
};
@@ -581,14 +644,14 @@ void GrapherWindow::on_menu_file_quit()
_quitting = true;
if (find_if(parsers.begin(), parsers.end(), !bind<bool>(PidPred(-1), _1))
!= parsers.end())
- _graphicalLauncher->killAll();
+ graphicalLauncher->killAll();
else
hide();
}
void GrapherWindow::on_menu_script_start()
{
- _graphicalLauncher->runDialog();
+ graphicalLauncher->runDialog();
}
@@ -609,23 +672,21 @@ void GrapherWindow::onParserListChanged()
int main(int argc, char** argv)
{
Gtk::Main app(argc, argv);
- GraphicalStapLauncher launcher;
+ graphicalLauncher = new GraphicalStapLauncher;
GrapherWindow win;
win.set_title("Grapher");
win.set_default_size(600, 250);
- win.setGraphicalLauncher(&launcher);
-
if (argc == 2 && !std::strcmp(argv[1], "-"))
{
- tr1::shared_ptr<StapParser> sp = launcher.makeStapParser();
+ tr1::shared_ptr<StapParser> sp = graphicalLauncher->makeStapParser();
sp->initIo(STDIN_FILENO, -1, true);
}
else if (argc > 1)
{
- launcher.setArgv(argv + 1);
- launcher.launch();
+ graphicalLauncher->setArgv(argv + 1);
+ graphicalLauncher->launch();
}
Gtk::Main::run(win);
return 0;