diff options
-rw-r--r-- | buildrun.cxx | 8 | ||||
-rw-r--r-- | main.cxx | 77 | ||||
-rw-r--r-- | util.cxx | 41 | ||||
-rw-r--r-- | util.h | 2 |
4 files changed, 47 insertions, 81 deletions
diff --git a/buildrun.cxx b/buildrun.cxx index 97357692..71a34c96 100644 --- a/buildrun.cxx +++ b/buildrun.cxx @@ -56,7 +56,7 @@ run_make_cmd(systemtap_session& s, string& make_cmd) make_cmd += " -s >/dev/null 2>&1"; if (s.verbose > 1) clog << "Running " << make_cmd << endl; - rc = system (make_cmd.c_str()); + rc = stap_system (make_cmd.c_str()); return rc; } @@ -223,7 +223,7 @@ kernel_built_uprobes (systemtap_session& s) { string grep_cmd = string ("/bin/grep -q unregister_uprobe ") + s.kernel_build_tree + string ("/Module.symvers"); - int rc = system (grep_cmd.c_str()); + int rc = stap_system (grep_cmd.c_str()); return (rc == 0); } @@ -274,7 +274,7 @@ copy_uprobes_symbols (systemtap_session& s) string uprobes_home = s.runtime_path + "/uprobes"; string cp_cmd = string("/bin/cp ") + uprobes_home + string("/Module.symvers ") + s.tmpdir; - int rc = system (cp_cmd.c_str()); + int rc = stap_system (cp_cmd.c_str()); return rc; } @@ -339,7 +339,7 @@ run_pass (systemtap_session& s) if (s.verbose>1) clog << "Running " << staprun_cmd << endl; - rc = system (staprun_cmd.c_str ()); + rc = stap_system (staprun_cmd.c_str ()); return rc; } @@ -36,8 +36,6 @@ 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> @@ -293,14 +291,9 @@ int pending_interrupts; extern "C" void handle_interrupt (int sig) { - if (pending_interrupts == 0) - kill (0, sig); // Forward signals to child processes if any. - + kill_stap_spawn(sig); pending_interrupts ++; - // NB: the "2" below is intended to skip the effect of the self-induced - // deferred signal coming from the kill() above. - - if (pending_interrupts > 2) // XXX: should be configurable? time-based? + if (pending_interrupts > 1) // XXX: should be configurable? time-based? { char msg[] = "Too many interrupts received, exiting.\n"; int rc = write (2, msg, sizeof(msg)-1); @@ -324,7 +317,7 @@ setup_signals (sighandler_t handler) sigaddset (&sa.sa_mask, SIGINT); sigaddset (&sa.sa_mask, SIGTERM); } - sa.sa_flags = 0; + sa.sa_flags = SA_RESTART; sigaction (SIGHUP, &sa, NULL); sigaction (SIGPIPE, &sa, NULL); @@ -332,62 +325,10 @@ 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; @@ -899,16 +840,6 @@ runner (int argc, char * const argv []) // directory. s.translated_source = string(s.tmpdir) + "/" + s.module_name + ".c"; - // 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 (). - if (setpgrp() != 0) - { - const char* e = strerror (errno); - if (! s.suppress_warnings) - cerr << "Warning: failed to set new process group: " << e << endl; - } - // Set up our handler to catch routine signals, to allow clean // and reasonably timely exit. setup_signals(&handle_interrupt); @@ -1251,7 +1182,7 @@ pass_5: string cleanupcmd = "rm -rf "; cleanupcmd += s.tmpdir; if (s.verbose>1) clog << "Running " << cleanupcmd << endl; - int status = system (cleanupcmd.c_str()); + int status = stap_system (cleanupcmd.c_str()); if (status != 0 && s.verbose>1) clog << "Cleanup command failed, status: " << status << endl; } @@ -20,13 +20,15 @@ #include <cerrno> extern "C" { -#include <sys/types.h> -#include <sys/stat.h> +#include <fcntl.h> #include <pwd.h> -#include <unistd.h> +#include <spawn.h> #include <stdio.h> #include <stdlib.h> -#include <fcntl.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <sys/wait.h> +#include <unistd.h> } using namespace std; @@ -275,4 +277,35 @@ git_revision(const string& path) return revision; } + +static pid_t spawned_pid = 0; + +// Runs a command with a saved PID, so we can kill it from the signal handler +int +stap_system(const char *command) +{ + const char * argv[] = { "sh", "-c", command, NULL }; + int ret, status; + + spawned_pid = 0; + ret = posix_spawn(&spawned_pid, "/bin/sh", NULL, NULL, + const_cast<char **>(argv), environ); + if (ret == 0) + { + if (waitpid(spawned_pid, &status, 0) == spawned_pid) + ret = WIFEXITED(status) ? WEXITSTATUS(status) : 128 + WTERMSIG(status); + else + ret = errno; + } + spawned_pid = 0; + return ret; +} + +// Send a signal to our spawned command +int +kill_stap_spawn(int sig) +{ + return spawned_pid ? kill(spawned_pid, sig) : 0; +} + /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */ @@ -13,6 +13,8 @@ void tokenize(const std::string& str, std::vector<std::string>& tokens, std::string find_executable(const std::string& name); const std::string cmdstr_quoted(const std::string& cmd); std::string git_revision(const std::string& path); +int stap_system(const char *command); +int kill_stap_spawn(int sig); // stringification generics |