summaryrefslogtreecommitdiffstats
path: root/main.cxx
diff options
context:
space:
mode:
authorMark Wielaard <mjw@redhat.com>2009-03-31 12:15:09 +0200
committerMark Wielaard <mjw@redhat.com>2009-03-31 12:28:59 +0200
commitff41ddbb9f40fbcc4bb0aa11ca0d8e03b369b606 (patch)
treecf6ca35817b0d2b53074732e9ccbbbc3359cccea /main.cxx
parentbd0b450c6327b1666385f4e5fb5d23382cbffc86 (diff)
downloadsystemtap-steved-ff41ddbb9f40fbcc4bb0aa11ca0d8e03b369b606.tar.gz
systemtap-steved-ff41ddbb9f40fbcc4bb0aa11ca0d8e03b369b606.tar.xz
systemtap-steved-ff41ddbb9f40fbcc4bb0aa11ca0d8e03b369b606.zip
PR10016: Run stap in its own process group with waiter process for signals.
* main.cxx (runner): New main function. (waiter_handler): Signal handler for waiter process. (waiter): Waiter process waitpid function. (main): Fork and run wait and runner in their own processes.
Diffstat (limited to 'main.cxx')
-rw-r--r--main.cxx58
1 files changed, 56 insertions, 2 deletions
diff --git a/main.cxx b/main.cxx
index 23b182eb..3b88a1c8 100644
--- a/main.cxx
+++ b/main.cxx
@@ -36,6 +36,8 @@ extern "C" {
#include <sys/times.h>
#include <sys/time.h>
#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/wait.h>
#include <time.h>
#include <elfutils/libdwfl.h>
#include <getopt.h>
@@ -330,10 +332,62 @@ setup_signals (sighandler_t handler)
sigaction (SIGTERM, &sa, NULL);
}
+pid_t runner_pid;
+int runner (int, char * const []);
+
+// Passes on signals to runner process.
+// In practise passes signal to runner process process group,
+// since run_pass() uses system() to spawn child processes,
+// which makes the process ignore SIGINT during the command run.
+extern "C"
+void waiter_handler (int sig)
+{
+ // Process group is negative process id.
+ kill (-1 * runner_pid, sig);
+}
+
+// Just sits there till the runner exits and then exits the same way.
+void waiter()
+{
+ int status;
+ setup_signals (&waiter_handler);
+ while (waitpid (runner_pid, &status, 0) != runner_pid);
+
+ // Exit as our runner child exitted.
+ if (WIFEXITED(status))
+ exit (WEXITSTATUS(status));
+
+ // Or simulate as if we were killed by the same signal.
+ if (WIFSIGNALED(status))
+ {
+ int sig = WTERMSIG(status);
+ signal (sig, SIG_DFL);
+ raise (sig);
+ }
+
+ // Should not happen, exit as if error.
+ exit(-1);
+}
int
main (int argc, char * const argv [])
{
+ // Fork to make sure runner gets its own process group, while
+ // the waiter sits in the original process group of the shell
+ // and forwards any signals.
+ runner_pid = fork ();
+ if (runner_pid == 0)
+ return runner (argc, argv);
+ if (runner_pid > 0)
+ waiter ();
+
+ perror ("couldn't fork");
+ exit (-1);
+}
+
+int
+runner (int argc, char * const argv [])
+{
string cmdline_script; // -e PROGRAM
string script_file; // FILE
bool have_script = false;
@@ -847,8 +901,8 @@ main (int argc, char * const argv [])
// We want a new process group so we can use kill (0, sig) to send a
// signal to all children (but not the parent). As done in
- // handle_interrupt (). Unless we are already the process group leader.
- if (getpgrp() != getpid() && setpgrp() != 0)
+ // handle_interrupt ().
+ if (setpgrp() != 0)
{
const char* e = strerror (errno);
if (! s.suppress_warnings)