diff options
author | Mark Wielaard <mjw@redhat.com> | 2009-03-31 12:15:09 +0200 |
---|---|---|
committer | Mark Wielaard <mjw@redhat.com> | 2009-03-31 12:28:59 +0200 |
commit | ff41ddbb9f40fbcc4bb0aa11ca0d8e03b369b606 (patch) | |
tree | cf6ca35817b0d2b53074732e9ccbbbc3359cccea /main.cxx | |
parent | bd0b450c6327b1666385f4e5fb5d23382cbffc86 (diff) | |
download | systemtap-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.cxx | 58 |
1 files changed, 56 insertions, 2 deletions
@@ -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) |