From 701c41be909697d5ab36f7604a1f3620c7d04abc Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Fri, 20 Mar 2009 13:31:18 -0400 Subject: PR6930: stap: supports on-file flight recorder options Add on-file flight recorder options (the combination of -F and -o, and -S option) to stap command, and change manpages and NEWS. - Both of -F and -o is specified, stap passes -D option to staprun. - stap just passes -S option to staprun. --- main.cxx | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'main.cxx') diff --git a/main.cxx b/main.cxx index 890f65bc..6f4064a5 100644 --- a/main.cxx +++ b/main.cxx @@ -111,7 +111,9 @@ usage (systemtap_session& s, int exitcode) << " -o FILE send script output to file, instead of stdout" << endl << " -c CMD start the probes, run CMD, and exit when it finishes" << endl << " -x PID sets target() to PID" << endl - << " -F load module and start probes, then detach" << endl + << " -F run as on-file flight recorder with -o." << endl + << " run as on-memory flight recorder without -o." << endl + << " -S size[,n] set maximum of the size and the number of files." << endl << " -d OBJECT add unwind/symbol data for OBJECT file"; if (s.unwindsym_modules.size() == 0) clog << endl; @@ -444,7 +446,7 @@ main (int argc, char * const argv []) { "vp", 1, &long_opt, LONG_OPT_VERBOSE_PASS }, { NULL, 0, NULL, 0 } }; - int grc = getopt_long (argc, argv, "hVMvtp:I:e:o:R:r:m:kgPc:x:D:bs:uqwl:d:L:F", + int grc = getopt_long (argc, argv, "hVMvtp:I:e:o:R:r:m:kgPc:x:D:bs:uqwl:d:L:FS:", long_options, NULL); if (grc < 0) break; @@ -628,6 +630,10 @@ main (int argc, char * const argv []) s.macros.push_back (string (optarg)); break; + case 'S': + s.size_option = string (optarg); + break; + case 'q': s.tapset_compile_coverage = true; break; -- cgit From 04ae1b090781725631ba3477ff77721b012cdaba Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Fri, 20 Mar 2009 13:38:29 -0400 Subject: PR9821: staprun supports subset of strftime. Add strftime subset format support for output file name to systemtap. This format will be evaluated when opening a new output file. --- main.cxx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'main.cxx') diff --git a/main.cxx b/main.cxx index 6f4064a5..cdcae41a 100644 --- a/main.cxx +++ b/main.cxx @@ -108,7 +108,9 @@ usage (systemtap_session& s, int exitcode) << " " << s.kernel_build_tree << endl << " -m MODULE set probe module name, instead of " << endl << " " << s.module_name << endl - << " -o FILE send script output to file, instead of stdout" << endl + << " -o FILE send script output to file, instead of stdout. This supports" << endl + << " a subset of strftime(3) (%%,%C,%Y,%y,%m,%d,%e,%F,%H,%I,%j,%k," << endl + << " %l,%M,%S,%R,%T,%u,%w) for FILE." << endl << " -c CMD start the probes, run CMD, and exit when it finishes" << endl << " -x PID sets target() to PID" << endl << " -F run as on-file flight recorder with -o." << endl -- cgit From 28f569c22b5a4ec666be5ccdf26fd194d3643c29 Mon Sep 17 00:00:00 2001 From: "Frank Ch. Eigler" Date: Fri, 27 Mar 2009 12:07:49 -0400 Subject: initialize skip_badvars=0. rererenag developers in session.h to do so in the future --- main.cxx | 1 + 1 file changed, 1 insertion(+) (limited to 'main.cxx') diff --git a/main.cxx b/main.cxx index cdcae41a..055c56b8 100644 --- a/main.cxx +++ b/main.cxx @@ -379,6 +379,7 @@ main (int argc, char * const argv []) s.ignore_vmlinux = false; s.ignore_dwarf = false; s.load_only = false; + s.skip_badvars = false; const char* s_p = getenv ("SYSTEMTAP_TAPSET"); if (s_p != NULL) -- cgit From bcc2b3536d6efb5857c16704f99b772655981cdd Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Mon, 30 Mar 2009 21:18:30 +0200 Subject: PR10016: systemtap kills all processes in process group on signal. * main.cxx (main): Make sure we run in our own process group. --- main.cxx | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'main.cxx') diff --git a/main.cxx b/main.cxx index 055c56b8..23b182eb 100644 --- a/main.cxx +++ b/main.cxx @@ -845,6 +845,16 @@ main (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 (). Unless we are already the process group leader. + if (getpgrp() != getpid() && 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); -- cgit From ff41ddbb9f40fbcc4bb0aa11ca0d8e03b369b606 Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Tue, 31 Mar 2009 12:15:09 +0200 Subject: 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. --- main.cxx | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 56 insertions(+), 2 deletions(-) (limited to 'main.cxx') 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 #include #include +#include +#include #include #include #include @@ -330,9 +332,61 @@ 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 @@ -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) -- cgit From 4cc40e829870dd6a1d9714706d38f5fd4b2ec982 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Wed, 1 Apr 2009 14:49:12 -0700 Subject: PR10016: Purge stap of all pgrp and system() usage We hereby no longer try to manipulate process groups in any way. We don't set a private process group, and we never kill() our entire group either. Instead of using system(), we now have a stap_system() which saves the child PID, so when we get a terminating signal we can pass it along to the child. Signals sent through the TTY have always worked, since the TTY sends it to the entire pgrp. However, if we're running as part of a wrapper script or GUI, which may not have a separate process group for stap, we still would like to allow "kill -TERM $STAPPID" to terminate stap nicely. There's still a short window of failure in the time that staprun is active, because we can't kill a setuid process from a user process. Once staprun drops privileges and execs to stapio though, everything should work fine. --- main.cxx | 77 ++++------------------------------------------------------------ 1 file changed, 4 insertions(+), 73 deletions(-) (limited to 'main.cxx') diff --git a/main.cxx b/main.cxx index 3b88a1c8..794a5891 100644 --- a/main.cxx +++ b/main.cxx @@ -36,8 +36,6 @@ extern "C" { #include #include #include -#include -#include #include #include #include @@ -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,61 +325,9 @@ 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 @@ -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; } -- cgit From 755cdd9b9c502b54324a3c56d8fda7fc1ad1fa88 Mon Sep 17 00:00:00 2001 From: Kent Sebastian Date: Fri, 17 Apr 2009 16:20:09 -0400 Subject: PR10082: add environment variable to pass -r RELEASE/PATH option --- main.cxx | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) (limited to 'main.cxx') diff --git a/main.cxx b/main.cxx index 794a5891..37c5b135 100644 --- a/main.cxx +++ b/main.cxx @@ -425,6 +425,36 @@ main (int argc, char * const argv []) if (s_tc != NULL) s.tapset_compile_coverage = true; + const char* s_kr = getenv ("SYSTEMTAP_RELEASE"); + if (s_kr != NULL) { + if (s_kr[0] == '/') // fully specified path + { + s.kernel_build_tree = s_kr; + string version_file_name = s.kernel_build_tree + "/include/config/kernel.release"; + // The file include/config/kernel.release within the + // build tree is used to pull out the version information + ifstream version_file (version_file_name.c_str()); + if (version_file.fail ()) + { + cerr << "Missing " << version_file_name << endl; + exit(1); + } + else + { + char c; + s.kernel_release = ""; + while (version_file.get(c) && c != '\n') + s.kernel_release.push_back(c); + } + } + else + { + s.kernel_release = string (s_kr); + s.kernel_build_tree = "/lib/modules/" + s.kernel_release + "/build"; + } + } + + while (true) { int long_opt; -- cgit From 54f1da8faec0408630348f70d78fc0f8ca07f876 Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Wed, 22 Apr 2009 13:16:25 -0400 Subject: PR 9821: Use genuine strftime in staprun/stapio * Makefile.am: Add -fno-builtin-strftime to stapio_CFLAGS. * Makefile.in: Ditto. * runtime/staprun/common.c (stap_strfloctime): Use strftime(3). (parse_args): Remove strftime format limitation message. * main.cxx (usage): Ditto. * stap.1.in: Ditto. * staprun.8.in: Ditto. --- main.cxx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'main.cxx') diff --git a/main.cxx b/main.cxx index 37c5b135..1111b316 100644 --- a/main.cxx +++ b/main.cxx @@ -109,8 +109,7 @@ usage (systemtap_session& s, int exitcode) << " -m MODULE set probe module name, instead of " << endl << " " << s.module_name << endl << " -o FILE send script output to file, instead of stdout. This supports" << endl - << " a subset of strftime(3) (%%,%C,%Y,%y,%m,%d,%e,%F,%H,%I,%j,%k," << endl - << " %l,%M,%S,%R,%T,%u,%w) for FILE." << endl + << " strftime(3) formats for FILE" << endl << " -c CMD start the probes, run CMD, and exit when it finishes" << endl << " -x PID sets target() to PID" << endl << " -F run as on-file flight recorder with -o." << endl -- cgit From 4d0a333004c652a75304c8276e4a45083ca9c122 Mon Sep 17 00:00:00 2001 From: Kent Sebastian Date: Fri, 24 Apr 2009 11:26:51 -0400 Subject: PR10082: refactor duplicated code --- main.cxx | 80 ++++++++++++++++++++++++---------------------------------------- 1 file changed, 30 insertions(+), 50 deletions(-) (limited to 'main.cxx') diff --git a/main.cxx b/main.cxx index 1111b316..ab568c23 100644 --- a/main.cxx +++ b/main.cxx @@ -324,6 +324,34 @@ setup_signals (sighandler_t handler) sigaction (SIGTERM, &sa, NULL); } +void +setup_kernel_release (systemtap_session &s, const char* kstr) { + if (kstr[0] == '/') // fully specified path + { + s.kernel_build_tree = kstr; + string version_file_name = s.kernel_build_tree + "/include/config/kernel.release"; + // The file include/config/kernel.release within the + // build tree is used to pull out the version information + ifstream version_file (version_file_name.c_str()); + if (version_file.fail ()) + { + cerr << "Missing " << version_file_name << endl; + exit(1); + } + else + { + char c; + s.kernel_release = ""; + while (version_file.get(c) && c != '\n') + s.kernel_release.push_back(c); + } + } + else + { + s.kernel_release = string (kstr); + s.kernel_build_tree = "/lib/modules/" + s.kernel_release + "/build"; + } +} int main (int argc, char * const argv []) @@ -426,31 +454,7 @@ main (int argc, char * const argv []) const char* s_kr = getenv ("SYSTEMTAP_RELEASE"); if (s_kr != NULL) { - if (s_kr[0] == '/') // fully specified path - { - s.kernel_build_tree = s_kr; - string version_file_name = s.kernel_build_tree + "/include/config/kernel.release"; - // The file include/config/kernel.release within the - // build tree is used to pull out the version information - ifstream version_file (version_file_name.c_str()); - if (version_file.fail ()) - { - cerr << "Missing " << version_file_name << endl; - exit(1); - } - else - { - char c; - s.kernel_release = ""; - while (version_file.get(c) && c != '\n') - s.kernel_release.push_back(c); - } - } - else - { - s.kernel_release = string (s_kr); - s.kernel_build_tree = "/lib/modules/" + s.kernel_release + "/build"; - } + setup_kernel_release(s, s_kr); } @@ -588,31 +592,7 @@ main (int argc, char * const argv []) break; case 'r': - if (optarg[0] == '/') // fully specified path - { - s.kernel_build_tree = optarg; - string version_file_name = s.kernel_build_tree + "/include/config/kernel.release"; - // The file include/config/kernel.release within the - // build tree is used to pull out the version information - ifstream version_file (version_file_name.c_str()); - if (version_file.fail ()) - { - cerr << "Missing " << version_file_name << endl; - usage (s, 1); - } - else - { - char c; - s.kernel_release = ""; - while (version_file.get(c) && c != '\n') - s.kernel_release.push_back(c); - } - } - else - { - s.kernel_release = string (optarg); - s.kernel_build_tree = "/lib/modules/" + s.kernel_release + "/build"; - } + setup_kernel_release(s, optarg); break; case 'k': -- cgit From 2035bcd40b17832439df0a1eb28403b99a71b74f Mon Sep 17 00:00:00 2001 From: Dave Brolley Date: Mon, 4 May 2009 16:05:22 -0400 Subject: Module signing and verification using a separate file for the module signature. --- main.cxx | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'main.cxx') diff --git a/main.cxx b/main.cxx index ab568c23..1ac5dd5a 100644 --- a/main.cxx +++ b/main.cxx @@ -403,6 +403,14 @@ main (int argc, char * const argv []) s.load_only = false; s.skip_badvars = false; + // Location of our signing certificate. + // If we're root, use the database in SYSCONFDIR, otherwise + // use the one in our $HOME directory. */ + if (geteuid() == 0) + s.cert_db_path = SYSCONFDIR "/systemtap/ssl/server"; + else + s.cert_db_path = getenv("HOME") + string ("/.systemtap/ssl/server"); + const char* s_p = getenv ("SYSTEMTAP_TAPSET"); if (s_p != NULL) { @@ -1134,6 +1142,20 @@ main (int argc, char * const argv []) if (copy_file(module_src_path.c_str(), module_dest_path.c_str()) != 0) cerr << "Copy failed (\"" << module_src_path << "\" to \"" << module_dest_path << "\"): " << strerror(errno) << endl; + +#if HAVE_NSS + // Save the signature as well. + assert (! s.cert_db_path.empty()); + module_src_path += ".sgn"; + module_dest_path += ".sgn"; + + if (s.verbose > 1) + clog << "Copying " << module_src_path << " to " + << module_dest_path << endl; + if (copy_file(module_src_path.c_str(), module_dest_path.c_str()) != 0) + cerr << "Copy failed (\"" << module_src_path << "\" to \"" + << module_dest_path << "\"): " << strerror(errno) << endl; +#endif } } -- cgit