From aac88aab720d169bacc49702f18996a5929a7f5d Mon Sep 17 00:00:00 2001 From: Tim Moore Date: Wed, 16 Sep 2009 19:06:29 +0200 Subject: [PATCH] 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 --- grapher/StapParser.cxx | 27 +++++++++++- grapher/StapParser.hxx | 7 +++- grapher/grapher.cxx | 93 ++++++++++++++++++++++++++++++++++++++---- 3 files changed, 116 insertions(+), 11 deletions(-) diff --git a/grapher/StapParser.cxx b/grapher/StapParser.cxx index 47dfbe30f..74b081709 100644 --- a/grapher/StapParser.cxx +++ b/grapher/StapParser.cxx @@ -1,5 +1,7 @@ #include "StapParser.hxx" +#include + #include #include #include @@ -65,11 +67,16 @@ vector commaSplit(const string& inStr, size_t pos = 0) bool StapParser::ioCallback(Glib::IOCondition ioCondition) { using namespace std; + if (ioCondition & Glib::IO_HUP) + { + _win.hide(); + return true; + } if ((ioCondition & Glib::IO_IN) == 0) return true; char buf[256]; ssize_t bytes_read = 0; - bytes_read = read(0, buf, sizeof(buf) - 1); + bytes_read = read(STDIN_FILENO, buf, sizeof(buf) - 1); if (bytes_read <= 0) { _win.hide(); @@ -203,4 +210,22 @@ vector commaSplit(const string& inStr, size_t pos = 0) } return true; } + + bool StapParser::errIoCallback(Glib::IOCondition ioCondition) + { + using namespace std; + if ((ioCondition & Glib::IO_IN) == 0) + return true; + char buf[256]; + ssize_t bytes_read = 0; + bytes_read = read(_errFd, buf, sizeof(buf) - 1); + if (bytes_read <= 0) + { + _win.hide(); + return true; + } + if (write(STDOUT_FILENO, buf, bytes_read) < 0) + ; + return true; + } } diff --git a/grapher/StapParser.hxx b/grapher/StapParser.hxx index e11e7302e..f4f6bdefe 100644 --- a/grapher/StapParser.hxx +++ b/grapher/StapParser.hxx @@ -12,12 +12,15 @@ class StapParser CSVData _csv; Gtk::Window& _win; GraphWidget& _widget; + int _errFd; public: StapParser(Gtk::Window& win, - GraphWidget& widget) : _win(win), _widget(widget) {} + GraphWidget& widget) : _win(win), _widget(widget), _errFd(-1) {} void parseData(std::tr1::shared_ptr gdata, double time, const std::string& dataString); bool ioCallback(Glib::IOCondition ioCondition); - + bool errIoCallback(Glib::IOCondition ioCondition); + int getErrFd() { return _errFd; } + void setErrFd(int fd) { _errFd = fd; } }; } diff --git a/grapher/grapher.cxx b/grapher/grapher.cxx index ad7023f20..82e103f3f 100644 --- a/grapher/grapher.cxx +++ b/grapher/grapher.cxx @@ -9,6 +9,8 @@ #include #include +#include + #include #include #include @@ -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(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); -- 2.43.5