summaryrefslogtreecommitdiffstats
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
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
-rw-r--r--grapher/StapParser.cxx27
-rw-r--r--grapher/StapParser.hxx7
-rw-r--r--grapher/grapher.cxx93
3 files changed, 116 insertions, 11 deletions
diff --git a/grapher/StapParser.cxx b/grapher/StapParser.cxx
index 47dfbe30..74b08170 100644
--- a/grapher/StapParser.cxx
+++ b/grapher/StapParser.cxx
@@ -1,5 +1,7 @@
#include "StapParser.hxx"
+#include <unistd.h>
+
#include <gtkmm/window.h>
#include <iostream>
#include <sstream>
@@ -65,11 +67,16 @@ vector<string> 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<string> 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 e11e7302..f4f6bdef 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<GraphDataBase> 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 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);