summaryrefslogtreecommitdiffstats
path: root/grapher/grapher.cxx
diff options
context:
space:
mode:
authorTim Moore <timoore@redhat.com>2009-09-16 19:06:29 +0200
committerTim Moore <timoore@redhat.com>2009-09-30 20:40:30 +0200
commitaac88aab720d169bacc49702f18996a5929a7f5d (patch)
tree592585b2932c52f6ce4924db5ea4f492cf1e3bb4 /grapher/grapher.cxx
parent239edc45bc2215485362eda09422e380f02ad0c1 (diff)
downloadsystemtap-steved-aac88aab720d169bacc49702f18996a5929a7f5d.tar.gz
systemtap-steved-aac88aab720d169bacc49702f18996a5929a7f5d.tar.xz
systemtap-steved-aac88aab720d169bacc49702f18996a5929a7f5d.zip
grapher: Handle the death of the child stap process
* grapher/grapher.c (main): Set up signal and i/o handlers to detect death of child. * grapher/StapParser.cxx (errIoCallback): New method
Diffstat (limited to 'grapher/grapher.cxx')
-rw-r--r--grapher/grapher.cxx93
1 files changed, 85 insertions, 8 deletions
diff --git a/grapher/grapher.cxx b/grapher/grapher.cxx
index ad7023f2..82e103f3 100644
--- a/grapher/grapher.cxx
+++ b/grapher/grapher.cxx
@@ -9,6 +9,8 @@
#include <string>
#include <map>
+#include <signal.h>
+
#include <gtkmm.h>
#include <gtkmm/stock.h>
#include <gtkmm/main.h>
@@ -90,6 +92,45 @@ void GrapherWindow::on_menu_file_quit()
hide();
}
+// magic for noticing that the child stap process has died.
+int childPid = -1;
+
+int signalPipe[2] = {-1, -1};
+
+extern "C"
+{
+ void handleChild(int signum, siginfo_t* info, void* context)
+ {
+ char buf[1];
+ buf[0] = 1;
+ ssize_t err = write(signalPipe[1], buf, 1);
+ }
+}
+
+class SignalReader
+{
+public:
+ SignalReader(GrapherWindow& win_, int sigfd_) : win(win_), sigfd(sigfd_) {}
+ bool ioCallback(Glib::IOCondition ioCondition)
+ {
+ if ((ioCondition & Glib::IO_IN) == 0)
+ return true;
+ char buf;
+
+ if (read(sigfd, &buf, 1) <= 0)
+ return true;
+ int status;
+ while (wait(&status) != -1)
+ ;
+ childPid = -1;
+ win.hide();
+ return true;
+ }
+private:
+ GrapherWindow& win;
+ int sigfd;
+};
+
int main(int argc, char** argv)
{
Gtk::Main app(argc, argv);
@@ -101,11 +142,26 @@ int main(int argc, char** argv)
StapParser stapParser(win, win.w);
- int childPid = -1;
+ int stapErrFd = -1;
if (argc > 1)
{
- int pipefd[2];
- if (pipe(pipefd) < 0)
+ if (pipe(&signalPipe[0]) < 0)
+ {
+ std::perror("pipe");
+ exit(1);
+ }
+ 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)
+ {
+ std::perror("pipe");
+ exit(1);
+ }
+ if (pipe(&pipefd[2]) < 0)
{
std::perror("pipe");
exit(1);
@@ -116,13 +172,19 @@ int main(int argc, char** argv)
}
else if (childPid)
{
- dup2(pipefd[0], 0);
+ dup2(pipefd[0], STDIN_FILENO);
+ stapErrFd = pipefd[2];
close(pipefd[0]);
+ close(pipefd[1]);
+ close(pipefd[3]);
}
else
{
- dup2(pipefd[1], 1);
- close(pipefd[1]);
+ dup2(pipefd[1], STDOUT_FILENO);
+ dup2(pipefd[3], STDERR_FILENO);
+ for (int i = 0; i < 4; ++i)
+ close(pipefd[i]);
+
execlp("stap", "stap", argv[1], static_cast<char*>(0));
exit(1);
return 1;
@@ -130,8 +192,23 @@ int main(int argc, char** argv)
}
Glib::signal_io().connect(sigc::mem_fun(stapParser,
&StapParser::ioCallback),
- 0,
- Glib::IO_IN);
+ STDIN_FILENO,
+ Glib::IO_IN | Glib::IO_HUP);
+ if (stapErrFd >= 0)
+ {
+ stapParser.setErrFd(stapErrFd);
+ Glib::signal_io().connect(sigc::mem_fun(stapParser,
+ &StapParser::errIoCallback),
+ stapErrFd,
+ Glib::IO_IN);
+ }
+ SignalReader sigReader(win, signalPipe[0]);
+ if (signalPipe[0] >= 0)
+ {
+ Glib::signal_io().connect(sigc::mem_fun(sigReader,
+ &SignalReader::ioCallback),
+ signalPipe[0], Glib::IO_IN);
+ }
Gtk::Main::run(win);
if (childPid > 0)
kill(childPid, SIGTERM);