summaryrefslogtreecommitdiffstats
path: root/grapher/grapher.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'grapher/grapher.cxx')
-rw-r--r--grapher/grapher.cxx596
1 files changed, 413 insertions, 183 deletions
diff --git a/grapher/grapher.cxx b/grapher/grapher.cxx
index 969bc762..0111184a 100644
--- a/grapher/grapher.cxx
+++ b/grapher/grapher.cxx
@@ -1,3 +1,11 @@
+// systemtap grapher
+// Copyright (C) 2009 Red Hat Inc.
+//
+// This file is part of systemtap, and is free software. You can
+// redistribute it and/or modify it under the terms of the GNU General
+// Public License (GPL); either version 2, or (at your option) any
+// later version.
+
#include "GraphWidget.hxx"
#include "StapParser.hxx"
@@ -31,65 +39,85 @@
#include <getopt.h>
using namespace std;
+using namespace tr1;
using namespace systemtap;
// magic for noticing that the child stap process has died.
int signalPipe[2] = {-1, -1};
+struct ChildInfo
+ {
+ pid_t pid;
+ int waitInfo;
+};
+
extern "C"
-{
- void handleChild(int signum, siginfo_t* info, void* context)
- {
- char buf[1];
- ssize_t err;
- buf[0] = 1;
- err = write(signalPipe[1], buf, 1);
- }
+ {
+ void handleChild(int signum, siginfo_t* info, void* context)
+ {
+ struct ChildInfo childInfo;
+ ssize_t err;
+
+ // Loop doing waitpid because the SIGCHLD signal isn't queued;
+ // multiple signals might get lost. If we get an error because
+ // there are no zombie children (return value <= 0 because of
+ // WNOHANG or no children exist at all), assume that an earlier
+ // invocation of handleChild already cleaned them up.
+ while ((childInfo.pid = waitpid(-1, &childInfo.waitInfo, WNOHANG)))
+ {
+ if (childInfo.pid < 0 && errno != ECHILD)
+ {
+ char errbuf[256];
+ strerror_r(errno, errbuf, sizeof(errbuf));
+ err = write(STDERR_FILENO, errbuf, strlen(errbuf));
+ err = write(STDERR_FILENO, "\n", 1);
+ return;
+ }
+ else if (childInfo.pid > 0)
+ {
+ err = write(signalPipe[1], &childInfo, sizeof(childInfo));
+ }
+ else
+ return;
+ }
+ }
}
// Waits for a gtk I/O signal, indicating that a child has died, then
// performs an action
class ChildDeathReader
+ {
+ public:
+ ChildDeathReader() : sigfd(-1) {}
+ ChildDeathReader(int sigfd_) : sigfd(sigfd_) {}
+ int getSigfd() { return sigfd; }
+ void setSigfd(int sigfd_) { sigfd = sigfd_; }
+
+ bool ioCallback(Glib::IOCondition ioCondition)
+ {
+ if ((ioCondition & Glib::IO_IN) == 0)
+ return true;
+ ChildInfo info;
+ if (read(sigfd, &info, sizeof(info)) < static_cast<ssize_t>(sizeof(info)))
+ cerr << "couldn't read ChildInfo from signal handler\n";
+ else
+ childDiedSignal().emit(info.pid);
+ return true;
+ }
+private:
+ int sigfd;
+};
+
+struct PidPred
{
-public:
- struct Callback
- {
- virtual ~Callback() {}
- virtual void childDied(int pid) {}
- };
- ChildDeathReader() : sigfd(-1) {}
- ChildDeathReader(int sigfd_) : sigfd(sigfd_) {}
- int getSigfd() { return sigfd; }
- void setSigfd(int sigfd_) { sigfd = sigfd_; }
- virtual pid_t reap()
+ PidPred(pid_t pid_) : pid(pid_) {}
+ bool operator()(const shared_ptr<StapParser>& parser) const
{
- pid_t pid;
- int status;
- if ((pid = waitpid(-1, &status, WNOHANG)) == -1)
- {
- std::perror("waitpid");
- return -1;
- }
- else
- {
- return pid;
- }
- }
- bool ioCallback(Glib::IOCondition ioCondition)
- {
- if ((ioCondition & Glib::IO_IN) == 0)
- return true;
- char buf;
-
- if (read(sigfd, &buf, 1) <= 0)
- return true;
- reap();
- return true;
+ return parser->getPid() == pid;
}
-private:
- int sigfd;
+ pid_t pid;
};
// Depending on how args are passed, either launch stap directly or
@@ -97,14 +125,18 @@ private:
class StapLauncher : public ChildDeathReader
{
public:
- StapLauncher() : _argv(0), _childPid(-1), _deathCallback(0) {}
+ StapLauncher() : _argv(0), _childPid(-1)
+ {
+ childDiedSignal().connect(sigc::mem_fun(*this, &StapLauncher::onChildDied));
+ }
StapLauncher(char** argv)
- : _argv(argv), _childPid(-1), _deathCallback(0)
+ : _argv(argv), _childPid(-1)
{
+ childDiedSignal().connect(sigc::mem_fun(*this, &StapLauncher::onChildDied));
}
StapLauncher(const string& stapArgs, const string& script,
const string& scriptArgs)
- : _childPid(-1), _deathCallback(0), _win(0), _widget(0)
+ : _childPid(-1)
{
setArgs(stapArgs, script, scriptArgs);
}
@@ -121,6 +153,7 @@ public:
void setArgs(const string& stapArgs, const string& script,
const string& scriptArgs)
{
+ _argv = 0;
_stapArgs = stapArgs;
_script = script;
_scriptArgs = scriptArgs;
@@ -140,43 +173,42 @@ public:
_script.clear();
_scriptArgs.clear();
}
- void setDeathCallback(ChildDeathReader::Callback* callback)
- {
- _deathCallback = callback;
- }
- void setWinParams(Gtk::Window* win, GraphWidget* widget)
- {
- _win = win;
- _widget = widget;
- }
+
int launch();
- void cleanUp();
- tr1::shared_ptr<StapParser> makeStapParser()
+ int launchUsingParser(shared_ptr<StapParser> parser);
+ shared_ptr<StapParser> makeStapParser()
{
- tr1::shared_ptr<StapParser> result(new StapParser(_win, _widget));
- _parsers.push_back(ParserInstance(-1, result));
+ shared_ptr<StapParser> result(new StapParser);
+ parsers.push_back(result);
+ parserListChangedSignal().emit();
return result;
}
- pid_t reap()
+public:
+ void onChildDied(pid_t pid)
{
- 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);
- if (itr != _parsers.end())
- itr->childPid = -1;
- return pid;
+ = find_if(parsers.begin(), parsers.end(), PidPred(pid));
+ if (itr != parsers.end())
+ {
+ (*itr)->disconnect();
+ tr1::shared_ptr<StapProcess> sp = (*itr)->getProcess();
+ if (sp)
+ {
+ sp->pid = -1;
+ parserListChangedSignal().emit();
+ }
+ }
}
void killAll()
{
- for (ParserList::iterator itr = _parsers.begin(), end = _parsers.end();
+ ParserList parsersCopy(parsers.begin(), parsers.end());
+ for (ParserList::iterator itr = parsersCopy.begin(),
+ end = parsersCopy.end();
itr != end;
++itr)
{
- if (itr->childPid >= 0)
- kill(itr->childPid, SIGTERM);
+ if ((*itr)->getPid() >= 0)
+ kill((*itr)->getPid(), SIGTERM);
}
}
protected:
@@ -185,26 +217,40 @@ protected:
string _script;
string _scriptArgs;
int _childPid;
- ChildDeathReader::Callback* _deathCallback;
- Gtk::Window* _win;
- GraphWidget* _widget;
- struct ParserInstance
- {
- ParserInstance() : childPid(-1) {}
- ParserInstance(int childPid_, tr1::shared_ptr<StapParser> stapParser_)
- : childPid(childPid_), stapParser(stapParser_)
- {
- }
- pid_t childPid;
- tr1::shared_ptr<StapParser> stapParser;
- };
- typedef vector<ParserInstance> ParserList;
- ParserList _parsers;
};
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)
@@ -219,28 +265,23 @@ int StapLauncher::launch()
&ChildDeathReader::ioCallback),
signalPipe[0], Glib::IO_IN);
}
+ struct sigaction action;
+ action.sa_sigaction = handleChild;
+ sigemptyset(&action.sa_mask);
+ action.sa_flags = SA_SIGINFO | SA_NOCLDSTOP;
+ sigaction(SIGCLD, &action, 0);
}
- struct sigaction action;
- action.sa_sigaction = handleChild;
- sigemptyset(&action.sa_mask);
- action.sa_flags = SA_SIGINFO | SA_NOCLDSTOP;
- sigaction(SIGCLD, &action, 0);
int pipefd[4];
- if (pipe(&pipefd[0]) < 0)
+ if (pipe(&pipefd[0]) < 0 || pipe(&pipefd[2]) < 0)
{
std::perror("pipe");
exit(1);
}
- if (pipe(&pipefd[2]) < 0)
+ if ((proc->pid = fork()) == -1)
{
- std::perror("pipe");
exit(1);
}
- if ((childPid = fork()) == -1)
- {
- exit(1);
- }
- else if (childPid)
+ else if (proc->pid)
{
close(pipefd[1]);
close(pipefd[3]);
@@ -251,73 +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(_win, _widget));
- _parsers.push_back(ParserInstance(childPid, sp));
- sp->setErrFd(pipefd[2]);
- sp->setInFd(pipefd[0]);
- Glib::signal_io().connect(sigc::mem_fun(sp.get(),
- &StapParser::errIoCallback),
- pipefd[2],
- Glib::IO_IN);
- Glib::signal_io().connect(sigc::mem_fun(sp.get(),
- &StapParser::ioCallback),
- pipefd[0],
- Glib::IO_IN | Glib::IO_HUP);
- return childPid;
-}
-
-void StapLauncher::cleanUp()
-{
- struct sigaction action;
- action.sa_handler = SIG_DFL;
- sigemptyset(&action.sa_mask);
- action.sa_flags = 0;
- sigaction(SIGCLD, &action, 0);
- // Drain any outstanding signals
- close(signalPipe[1]);
- char buf;
- while (read(signalPipe[0], &buf, 1) > 0)
- reap();
- for (ParserList::iterator itr = _parsers.begin(), end = _parsers.end();
- itr != end;
- ++itr)
- {
- if (itr->childPid > 0)
- kill(itr->childPid, SIGTERM);
- int status;
- pid_t killedPid = -1;
- if ((killedPid = wait(&status)) == -1)
- {
- std::perror("wait");
- }
- else if (killedPid != itr->childPid)
- {
- std::cerr << "wait: killed Pid " << killedPid << " != child Pid "
- << itr->childPid << "\n";
- }
- else if (_deathCallback)
- _deathCallback->childDied(itr->childPid);
- }
+ sp->initIo(pipefd[0], pipefd[2], false);
+ return proc->pid;
}
class GraphicalStapLauncher : public StapLauncher
@@ -335,7 +331,229 @@ private:
Gtk::Entry* _scriptArgEntry;
};
-class GrapherWindow : public Gtk::Window, public ChildDeathReader::Callback
+GraphicalStapLauncher *graphicalLauncher = 0;
+
+class ProcModelColumns : public Gtk::TreeModelColumnRecord
+{
+public:
+ ProcModelColumns()
+ {
+ add(_iconName);
+ add(_scriptName);
+ add(_parser);
+ }
+ Gtk::TreeModelColumn<Glib::ustring> _iconName;
+ Gtk::TreeModelColumn<Glib::ustring> _scriptName;
+ Gtk::TreeModelColumn<shared_ptr<StapParser> > _parser;
+};
+
+// This should probably be a Gtk window, with the appropriate glade magic
+class ProcWindow
+{
+public:
+ ProcWindow();
+ ProcModelColumns _modelColumns;
+ Glib::RefPtr<Gnome::Glade::Xml> _xml;
+ Gtk::Window* _window;
+ Gtk::TreeView* _dataTreeView;
+ Gtk::Button* _killButton;
+ Gtk::Button* _restartButton;
+ Gtk::Label* _stapArgsLabel;
+ Gtk::Label* _scriptArgsLabel;
+ Glib::RefPtr<Gtk::ListStore> _listStore;
+ Glib::RefPtr<Gtk::TreeSelection> _listSelection;
+ void onClose();
+ void show();
+ void hide();
+ void onParserListChanged();
+ void onSelectionChanged();
+ void onKill();
+ void onRestart();
+private:
+ bool _open;
+ void refresh();
+};
+
+ProcWindow::ProcWindow()
+ : _open(false)
+{
+ 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);
+ // Display a nice icon for the state of the process
+ Gtk::CellRendererPixbuf* cell = Gtk::manage(new Gtk::CellRendererPixbuf);
+ _dataTreeView->append_column("State", *cell);
+ Gtk::TreeViewColumn* column = _dataTreeView->get_column(0);
+ if (column)
+ column->add_attribute(cell->property_icon_name(), _modelColumns._iconName);
+ _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);
+ _xml->get_widget("button1", _killButton);
+ _killButton->signal_clicked()
+ .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));
+ _listSelection = _dataTreeView->get_selection();
+ _listSelection->signal_changed()
+ .connect(sigc::mem_fun(*this, &ProcWindow::onSelectionChanged));
+ _xml->get_widget("label7", _stapArgsLabel);
+ _xml->get_widget("label8", _scriptArgsLabel);
+}
+
+void ProcWindow::onClose()
+{
+ _window->hide();
+}
+
+void ProcWindow::show()
+{
+ _open = true;
+ refresh();
+ _window->show();
+
+}
+
+void ProcWindow::hide()
+{
+ _open = false;
+ _window->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<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;
+ }
+ 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;
+ }
+ }
+ }
+}
+
+void ProcWindow::onParserListChanged()
+{
+ if (_open)
+ {
+ refresh();
+ _window->queue_draw();
+ }
+}
+
+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;
+ parser = row[_modelColumns._parser];
+ proc = parser->getProcess();
+ }
+ if (proc)
+ {
+ 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("");
+ }
+}
+
+void ProcWindow::onKill()
+{
+ 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 && 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:
GrapherWindow();
@@ -343,34 +561,33 @@ public:
Gtk::VBox m_Box;
Gtk::ScrolledWindow scrolled;
GraphWidget w;
- void childDied(int pid);
- void setGraphicalLauncher(GraphicalStapLauncher* launcher)
- {
- _graphicalLauncher = launcher;
- }
- GraphicalStapLauncher* getGraphicalLauncher() { return _graphicalLauncher; }
protected:
virtual void on_menu_file_quit();
virtual void on_menu_script_start();
+ virtual void on_menu_proc_window();
void addGraph();
+ void onParserListChanged();
// menu support
Glib::RefPtr<Gtk::UIManager> m_refUIManager;
Glib::RefPtr<Gtk::ActionGroup> m_refActionGroup;
- GraphicalStapLauncher* _graphicalLauncher;
-
+ shared_ptr<ProcWindow> _procWindow;
+ bool _quitting;
};
+
GrapherWindow::GrapherWindow()
+ : _procWindow(new ProcWindow), _quitting(false)
{
set_title("systemtap grapher");
add(m_Box);
-
+ parserListChangedSignal()
+ .connect(sigc::mem_fun(*this, &GrapherWindow::onParserListChanged));
//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"),
@@ -378,6 +595,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);
@@ -391,6 +614,9 @@ GrapherWindow::GrapherWindow()
" <menuitem action='AddGraph'/>"
" <menuitem action='FileQuit'/>"
" </menu>"
+ " <menu action='WindowMenu'>"
+ " <menuitem action='ProcessWindow'/>"
+ " </menu>"
" </menubar>"
"</ui>";
try
@@ -414,51 +640,55 @@ GrapherWindow::GrapherWindow()
void GrapherWindow::on_menu_file_quit()
{
- hide();
+ using namespace boost;
+ _quitting = true;
+ if (find_if(parsers.begin(), parsers.end(), !bind<bool>(PidPred(-1), _1))
+ != parsers.end())
+ graphicalLauncher->killAll();
+ else
+ hide();
}
void GrapherWindow::on_menu_script_start()
{
- _graphicalLauncher->runDialog();
+ graphicalLauncher->runDialog();
}
-void GrapherWindow::childDied(int pid)
+
+void GrapherWindow::on_menu_proc_window()
{
- hide();
+ _procWindow->show();
}
-
-
+void GrapherWindow::onParserListChanged()
+{
+ using namespace boost;
+ if (_quitting
+ && (find_if(parsers.begin(), parsers.end(), !bind<bool>(PidPred(-1), _1))
+ == parsers.end()))
+ hide();
+}
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);
- launcher.setWinParams(&win, &win.w);
- win.setGraphicalLauncher(&launcher);
-
if (argc == 2 && !std::strcmp(argv[1], "-"))
{
- tr1::shared_ptr<StapParser> sp = launcher.makeStapParser();
- sp->setInFd(STDIN_FILENO);
- Glib::signal_io().connect(sigc::mem_fun(sp.get(),
- &StapParser::ioCallback),
- STDIN_FILENO,
- Glib::IO_IN | Glib::IO_HUP);
+ tr1::shared_ptr<StapParser> sp = graphicalLauncher->makeStapParser();
+ sp->initIo(STDIN_FILENO, -1, true);
}
else if (argc > 1)
{
- launcher.setArgv(argv + 1);
- launcher.setDeathCallback(&win);
- launcher.launch();
+ graphicalLauncher->setArgv(argv + 1);
+ graphicalLauncher->launch();
}
Gtk::Main::run(win);
- launcher.cleanUp();
return 0;
}