]> sourceware.org Git - systemtap.git/commitdiff
PR13306: introduce stap --suppress-handler-errors option
authorFrank Ch. Eigler <fche@redhat.com>
Thu, 1 Dec 2011 00:54:19 +0000 (19:54 -0500)
committerFrank Ch. Eigler <fche@redhat.com>
Thu, 1 Dec 2011 00:54:19 +0000 (19:54 -0500)
PR13306 asked for a way to skip handlers when probe alias prefixes
fail.  This implementation is a little bigger hammer, but believed
to be more generally useful.

* session.cxx: Initialize/copy/getopt new option.
* session.h: Store it.
* hash.cxx (find_script_hash): Mix it in.
* tapsets.cxx (common_probe_entryfn_epilogue): Skip various
  MAXERRORS/MAXSKIPPED processing when flag is set.
* tapset.h (common_probe_entryfn_epilogue): Drop middle default
  argument since it got confusing.  Add new argument.
* tapsets*.cxx (*::emit_module_decls): Update ..._epilogue callers.

12 files changed:
hash.cxx
session.cxx
session.h
tapset-been.cxx
tapset-itrace.cxx
tapset-mark.cxx
tapset-perfmon.cxx
tapset-procfs.cxx
tapset-timers.cxx
tapset-utrace.cxx
tapsets.cxx
tapsets.h

index 28e517ed74314e8198389000b76411b724789f2d..a38d4ad1d21de408d69a1073a59541d5ba89f001 100644 (file)
--- a/hash.cxx
+++ b/hash.cxx
@@ -219,16 +219,18 @@ find_script_hash (systemtap_session& s, const string& script)
   h.add("UID: ", getuid());
 
   // Hash user-specified arguments (that change the generated module).
-  h.add("Bulk Mode (-b): ", s.bulk_mode);                      // '-b'
-  h.add("Timing (-t): ", s.timing);                    // '-t'
-  h.add("Prologue Searching (-P): ", s.prologue_searching);            // '-P'
-  h.add("Ignore Vmlinux (--ignore-vmlinux): ", s.ignore_vmlinux);              // --ignore-vmlinux
-  h.add("Ignore Dwarf (--ignore-dwarf): ", s.ignore_dwarf);            // --ignore-dwarf
-  h.add("Consult Symtab (--kelf, --kmap): ", s.consult_symtab);                // --kelf, --kmap
-  h.add("Skip Badvars (--skip-badvars): ", s.skip_badvars);            // --skip-badvars
-  h.add("Privilege (--privilege): ", s.privilege);                     // --privilege=
-  h.add("Compatible (--compatible): ", s.compatible);                  // --compatible
-  h.add("Omit Werror (undocumented): ", s.omit_werror);                        // undocumented, evil
+  h.add("Bulk Mode (-b): ", s.bulk_mode);
+  h.add("Timing (-t): ", s.timing);
+  h.add("Prologue Searching (-P): ", s.prologue_searching);
+  h.add("Ignore Vmlinux (--ignore-vmlinux): ", s.ignore_vmlinux);
+  h.add("Ignore Dwarf (--ignore-dwarf): ", s.ignore_dwarf);
+  h.add("Consult Symtab (--kelf, --kmap): ", s.consult_symtab);
+  h.add("Skip Badvars (--skip-badvars): ", s.skip_badvars);
+  h.add("Privilege (--privilege): ", s.privilege);
+  h.add("Compatible (--compatible): ", s.compatible);
+  h.add("Omit Werror (undocumented): ", s.omit_werror);
+  h.add("Prologue Searching (-P): ", s.prologue_searching);
+  h.add("Error suppression (--suppress-handler-errors): ", s.suppress_handler_errors);
   if (!s.kernel_symtab_path.empty())   // --kmap
     {
       h.add("Kernel Symtab Path: ", s.kernel_symtab_path);
index d8bcdd3f16419fc6953b6b20638712f68376f5d4..4783b71cfaa1b5a49eb10fe1d95c29cfb4b0b34f 100644 (file)
@@ -144,6 +144,7 @@ systemtap_session::systemtap_session ():
   use_remote_prefix = false;
   systemtap_v_check = false;
   download_dbinfo = 0;
+  suppress_handler_errors = false;
   native_build = true; // presumed
 
   /*  adding in the XDG_DATA_DIRS variable path,
@@ -308,6 +309,7 @@ systemtap_session::systemtap_session (const systemtap_session& other,
   use_remote_prefix = other.use_remote_prefix;
   systemtap_v_check = other.systemtap_v_check;
   download_dbinfo = other.download_dbinfo;
+  suppress_handler_errors = other.suppress_handler_errors;
 
   include_path = other.include_path;
   runtime_path = other.runtime_path;
@@ -503,6 +505,8 @@ systemtap_session::usage (int exitcode)
     "              version dependent\n"
     "   --skip-badvars\n"
     "              substitute zero for bad context $variables\n"
+    "   --suppress-handler-errors\n"
+    "              catch all runtime errors, quietly skip probe handlers\n"
     "   --use-server[=SERVER-SPEC]\n"
     "              specify systemtap compile-servers\n"
     "   --list-servers[=PROPERTIES]\n"
@@ -578,6 +582,7 @@ systemtap_session::parse_cmdline (int argc, char * const argv [])
 #define LONG_OPT_DOWNLOAD_DEBUGINFO 26
 #define LONG_OPT_DUMP_PROBE_TYPES 27
 #define LONG_OPT_PRIVILEGE 28
+#define LONG_OPT_SUPPRESS_HANDLER_ERRORS 29
       // NB: also see find_hash(), usage(), switch stmt below, stap.1 man page
       static struct option long_options[] = {
         { "kelf", 0, &long_opt, LONG_OPT_KELF },
@@ -614,6 +619,7 @@ systemtap_session::parse_cmdline (int argc, char * const argv [])
         { "download-debuginfo", 2, &long_opt, LONG_OPT_DOWNLOAD_DEBUGINFO },
         { "dump-probe-types", 0, &long_opt, LONG_OPT_DUMP_PROBE_TYPES },
         { "privilege", 1, &long_opt, LONG_OPT_PRIVILEGE },
+        { "suppress-handler-errors", 0, &long_opt, LONG_OPT_SUPPRESS_HANDLER_ERRORS },
         { NULL, 0, NULL, 0 }
       };
       int grc = getopt_long (argc, argv, "hVvtp:I:e:o:R:r:a:m:kgPc:x:D:bs:uqwl:d:L:FS:B:WG:",
@@ -1126,6 +1132,10 @@ systemtap_session::parse_cmdline (int argc, char * const argv [])
              dump_probe_types = true;
              break;
 
+           case LONG_OPT_SUPPRESS_HANDLER_ERRORS:
+             suppress_handler_errors = true;
+             break;
+
             default:
               // NOTREACHED unless one added a getopt option but not a corresponding switch/case:
               cerr << _F("Unhandled long argument id %d", long_opt) << endl;
index c056abca6686a14e5aad7ff1fbdd65b2b4d016aa..98c1f6b27aca049659c3e57aaca0e2be8026a4e7 100644 (file)
--- a/session.h
+++ b/session.h
@@ -183,6 +183,7 @@ public:
   bool tmpdir_opt_set;
   bool dump_probe_types;
   int download_dbinfo;
+  bool suppress_handler_errors;
 
   // NB: It is very important for all of the above (and below) fields
   // to be cleared in the systemtap_session ctor (session.cxx).
index 6c9443ca321781ec1ada579020d4b7198713af3c..88b53724bc23313ef2cb7153549b2a55ab6d3453 100644 (file)
@@ -142,7 +142,7 @@ be_derived_probe_group::emit_module_decls (systemtap_session& s)
   common_probe_entryfn_prologue (s.op, "stp->state", "stp->probe",
                                 "_STP_PROBE_HANDLER_BEEN", false);
   s.op->newline() << "(*stp->probe->ph) (c);";
-  common_probe_entryfn_epilogue (s.op, false);
+  common_probe_entryfn_epilogue (s.op, false, s.suppress_handler_errors);
   s.op->newline(-1) << "}";
 }
 
index 7efd73a39f12dfe26d80bbcaaeb18892e10a9e77..1a9bf6796007d3ceffa307861a555140ccf204b7 100644 (file)
@@ -196,7 +196,7 @@ itrace_derived_probe_group::emit_module_decls (systemtap_session& s)
 
   // call probe function
   s.op->newline() << "(*p->probe->ph) (c);";
-  common_probe_entryfn_epilogue (s.op);
+  common_probe_entryfn_epilogue (s.op, true, s.suppress_handler_errors);
 
   s.op->newline() << "return;";
   s.op->newline(-1) << "}";
index 42b4c8e5e8a21c28f46b9dcb9b5e8401cd0d88ea..b06cbeecbf6e5db12068467bd5e19e21b216f25d 100644 (file)
@@ -518,7 +518,7 @@ mark_derived_probe_group::emit_module_decls (systemtap_session& s)
   s.op->newline() << "(*smp->probe->ph) (c);";
   s.op->newline() << "c->ips.kmark.mark_va_list = NULL;";
 
-  common_probe_entryfn_epilogue (s.op);
+  common_probe_entryfn_epilogue (s.op, true, s.suppress_handler_errors);
   s.op->newline(-1) << "}";
 
   return;
index 8bd51dbdfc7bebf576f31f41e29e80f53ce41e9f..fa8128f00061b4b941891b39ac9362fd282eb575 100644 (file)
@@ -157,7 +157,7 @@ perf_derived_probe_group::emit_module_decls (systemtap_session& s)
   s.op->newline(-1) << "}";
 
   s.op->newline() << "(*stp->probe->ph) (c);";
-  common_probe_entryfn_epilogue (s.op);
+  common_probe_entryfn_epilogue (s.op, true, s.suppress_handler_errors);
   s.op->newline(-1) << "}";
 }
 
index 05f413d82f4b3251307cfae856e84cdc0dad3012..fd0fa30bfee70a18a0d9af89d8af4048d08f7d81 100644 (file)
@@ -274,7 +274,7 @@ procfs_derived_probe_group::emit_module_decls (systemtap_session& s)
       s.op->newline() << "spp->needs_fill = 0;";
       s.op->newline() << "spp->count = strlen(spp->buffer);";
 
-      common_probe_entryfn_epilogue (s.op);
+      common_probe_entryfn_epilogue (s.op, true, s.suppress_handler_errors);
 
       s.op->newline() << "if (spp->needs_fill) {";
       s.op->newline(1) << "spp->needs_fill = 0;";
@@ -332,7 +332,7 @@ procfs_derived_probe_group::emit_module_decls (systemtap_session& s)
       s.op->newline(1) << "retval = count;";
       s.op->newline(-1) << "}";
 
-      common_probe_entryfn_epilogue (s.op);
+      common_probe_entryfn_epilogue (s.op, true, s.suppress_handler_errors);
     }
 
   s.op->newline() << "return retval;";
index 736fe0da18c246f2faac1a82d7227785b5b9df57..c991d5d5bb0d7331a8019eaaa5fad666643f745c 100644 (file)
@@ -131,7 +131,7 @@ timer_derived_probe_group::emit_module_decls (systemtap_session& s)
   common_probe_entryfn_prologue (s.op, "STAP_SESSION_RUNNING", "stp->probe",
                                 "_STP_PROBE_HANDLER_TIMER");
   s.op->newline() << "(*stp->probe->ph) (c);";
-  common_probe_entryfn_epilogue (s.op);
+  common_probe_entryfn_epilogue (s.op, true, s.suppress_handler_errors);
   s.op->newline(-1) << "}";
   s.op->newline(-1) << "}";
 }
@@ -318,7 +318,7 @@ hrtimer_derived_probe_group::emit_module_decls (systemtap_session& s)
   common_probe_entryfn_prologue (s.op, "STAP_SESSION_RUNNING", "stp->probe",
                                 "_STP_PROBE_HANDLER_HRTIMER");
   s.op->newline() << "(*stp->probe->ph) (c);";
-  common_probe_entryfn_epilogue (s.op);
+  common_probe_entryfn_epilogue (s.op, true, s.suppress_handler_errors);
   s.op->newline(-1) << "}";
   s.op->newline() << "return rc;";
   s.op->newline(-1) << "}";
@@ -457,7 +457,7 @@ profile_derived_probe_group::emit_module_decls (systemtap_session& s)
         }
       s.op->newline() << "if (c->last_error == NULL) probe->ph (c);";
     }
-  common_probe_entryfn_epilogue (s.op);
+  common_probe_entryfn_epilogue (s.op, true, s.suppress_handler_errors);
   s.op->newline(-1) << "}";
 
   s.op->newline() << "#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10)"; // == using_rpn of yore
index 8083d7752c93ebbaf8758ea45bf6ed9fe9705aae..64ba900f62b5252c9307f74a211fb284a606c51e 100644 (file)
@@ -836,7 +836,7 @@ utrace_derived_probe_group::emit_module_decls (systemtap_session& s)
 
       // call probe function
       s.op->newline() << "(*p->probe->ph) (c);";
-      common_probe_entryfn_epilogue (s.op);
+      common_probe_entryfn_epilogue (s.op, true, s.suppress_handler_errors);
 
       s.op->newline() << "return;";
       s.op->newline(-1) << "}";
@@ -865,7 +865,7 @@ utrace_derived_probe_group::emit_module_decls (systemtap_session& s)
 
       // call probe function
       s.op->newline() << "(*p->probe->ph) (c);";
-      common_probe_entryfn_epilogue (s.op);
+      common_probe_entryfn_epilogue (s.op, true, s.suppress_handler_errors);
 
       s.op->newline() << "if ((atomic_read (&session_state) != STAP_SESSION_STARTING) && (atomic_read (&session_state) != STAP_SESSION_RUNNING)) {";
       s.op->indent(1);
index 08021d541b433a412d1e628cb8274beb1586e051..af6bb11a37f49de14ea1501377c6ba58891acd06 100644 (file)
@@ -186,7 +186,8 @@ common_probe_entryfn_prologue (translator_output* o, string statestr,
 
 void
 common_probe_entryfn_epilogue (translator_output* o,
-                               bool overload_processing)
+                               bool overload_processing,
+                               bool suppress_handler_errors)
 {
   if (overload_processing)
     o->newline() << "#if defined(STP_TIMING) || defined(STP_OVERLOAD)";
@@ -221,6 +222,9 @@ common_probe_entryfn_epilogue (translator_output* o,
       // If we've spent more than STP_OVERLOAD_THRESHOLD cycles in a
       // probe during the last STP_OVERLOAD_INTERVAL cycles, the probe
       // has overloaded the system and we need to quit.
+      // NB: this is not suppressible via --suppress-runtime-errors,
+      // because this is a system safety metric that we cannot trust
+      // unprivileged users to override.
       o->newline() << "if (interval > STP_OVERLOAD_INTERVAL) {";
       o->newline(1) << "if (c->cycles_sum > STP_OVERLOAD_THRESHOLD) {";
       o->newline(1) << "_stp_error (\"probe overhead exceeded threshold\");";
@@ -243,28 +247,44 @@ common_probe_entryfn_epilogue (translator_output* o,
   o->newline() << "c->probe_name = 0;";
   o->newline() << "#endif";
   o->newline() << "c->probe_type = 0;";
+
+
   o->newline() << "if (unlikely (c->last_error && c->last_error[0])) {";
-  o->newline(1) << "if (c->last_stmt != NULL)";
-  o->newline(1) << "_stp_softerror (\"%s near %s\", c->last_error, c->last_stmt);";
-  o->newline(-1) << "else";
-  o->newline(1) << "_stp_softerror (\"%s\", c->last_error);";
-  o->indent(-1);
-  o->newline() << "atomic_inc (& error_count);";
-  o->newline() << "if (atomic_read (& error_count) > MAXERRORS) {";
-  o->newline(1) << "atomic_set (& session_state, STAP_SESSION_ERROR);";
-  o->newline() << "_stp_exit ();";
-  o->newline(-1) << "}";
+  o->indent(1);
+  if (suppress_handler_errors) // PR 13306
+    { 
+      o->newline() << "atomic_inc (& error_count);";
+    }
+  else
+    {
+      o->newline() << "if (c->last_stmt != NULL)";
+      o->newline(1) << "_stp_softerror (\"%s near %s\", c->last_error, c->last_stmt);";
+      o->newline(-1) << "else";
+      o->newline(1) << "_stp_softerror (\"%s\", c->last_error);";
+      o->indent(-1);
+      o->newline() << "atomic_inc (& error_count);";
+      o->newline() << "if (atomic_read (& error_count) > MAXERRORS) {";
+      o->newline(1) << "atomic_set (& session_state, STAP_SESSION_ERROR);";
+      o->newline() << "_stp_exit ();";
+      o->newline(-1) << "}";
+    }
+
   o->newline(-1) << "}";
+
+
   o->newline() << "atomic_dec (&c->busy);";
 
   o->newline(-1) << "probe_epilogue:"; // context is free
   o->indent(1);
 
-  // Check for excessive skip counts.
-  o->newline() << "if (unlikely (atomic_read (& skipped_count) > MAXSKIPPED)) {";
-  o->newline(1) << "if (unlikely (pseudo_atomic_cmpxchg(& session_state, STAP_SESSION_RUNNING, STAP_SESSION_ERROR) == STAP_SESSION_RUNNING))";
-  o->newline() << "_stp_error (\"Skipped too many probes, check MAXSKIPPED or try again with stap -t for more details.\");";
-  o->newline(-1) << "}";
+  if (! suppress_handler_errors) // PR 13306
+    {
+      // Check for excessive skip counts.
+      o->newline() << "if (unlikely (atomic_read (& skipped_count) > MAXSKIPPED)) {";
+      o->newline(1) << "if (unlikely (pseudo_atomic_cmpxchg(& session_state, STAP_SESSION_RUNNING, STAP_SESSION_ERROR) == STAP_SESSION_RUNNING))";
+      o->newline() << "_stp_error (\"Skipped too many probes, check MAXSKIPPED or try again with stap -t for more details.\");";
+      o->newline(-1) << "}";
+    }
 
   o->newline() << "#if INTERRUPTIBLE";
   o->newline() << "preempt_enable_no_resched ();";
@@ -4647,7 +4667,7 @@ dwarf_derived_probe_group::emit_module_decls (systemtap_session& s)
   s.op->newline() << "SET_REG_IP(regs, kprobes_ip);";
   s.op->newline(-1) << "}";
 
-  common_probe_entryfn_epilogue (s.op);
+  common_probe_entryfn_epilogue (s.op, true, s.suppress_handler_errors);
   s.op->newline() << "return 0;";
   s.op->newline(-1) << "}";
 
@@ -4690,7 +4710,7 @@ dwarf_derived_probe_group::emit_module_decls (systemtap_session& s)
   s.op->newline() << "SET_REG_IP(regs, kprobes_ip);";
   s.op->newline(-1) << "}";
 
-  common_probe_entryfn_epilogue (s.op);
+  common_probe_entryfn_epilogue (s.op, true, s.suppress_handler_errors);
   s.op->newline(-1) << "}";
   s.op->newline() << "return 0;";
   s.op->newline(-1) << "}";
@@ -7365,7 +7385,7 @@ uprobe_derived_probe_group::emit_module_decls (systemtap_session& s)
   s.op->newline() << "SET_REG_IP(regs, uprobes_ip);";
   s.op->newline(-1) << "}";
 
-  common_probe_entryfn_epilogue (s.op);
+  common_probe_entryfn_epilogue (s.op, true, s.suppress_handler_errors);
   s.op->newline(-1) << "}";
 
   s.op->newline() << "static void enter_uretprobe_probe (struct uretprobe_instance *inst, struct pt_regs *regs) {";
@@ -7396,7 +7416,7 @@ uprobe_derived_probe_group::emit_module_decls (systemtap_session& s)
   s.op->newline() << "SET_REG_IP(regs, uprobes_ip);";
   s.op->newline(-1) << "}";
 
-  common_probe_entryfn_epilogue (s.op);
+  common_probe_entryfn_epilogue (s.op, true, s.suppress_handler_errors);
   s.op->newline(-1) << "}";
 
   s.op->newline();
@@ -7772,7 +7792,7 @@ kprobe_derived_probe_group::emit_module_decls (systemtap_session& s)
   s.op->newline() << "SET_REG_IP(regs, kprobes_ip);";
   s.op->newline(-1) << "}";
 
-  common_probe_entryfn_epilogue (s.op);
+  common_probe_entryfn_epilogue (s.op, true, s.suppress_handler_errors);
   s.op->newline() << "return 0;";
   s.op->newline(-1) << "}";
 
@@ -7807,7 +7827,7 @@ kprobe_derived_probe_group::emit_module_decls (systemtap_session& s)
   s.op->newline() << "SET_REG_IP(regs, kprobes_ip);";
   s.op->newline(-1) << "}";
 
-  common_probe_entryfn_epilogue (s.op);
+  common_probe_entryfn_epilogue (s.op, true, s.suppress_handler_errors);
   s.op->newline() << "return 0;";
   s.op->newline(-1) << "}";
 
@@ -8278,7 +8298,7 @@ hwbkpt_derived_probe_group::emit_module_decls (systemtap_session& s)
   s.op->newline(1) << "c->kregs = regs;";
   s.op->newline(-1) << "}";
   s.op->newline() << "(*sdp->probe->ph) (c);";
-  common_probe_entryfn_epilogue (s.op);
+  common_probe_entryfn_epilogue (s.op, true, s.suppress_handler_errors);
   s.op->newline(-1) << "}";
   s.op->newline(-1) << "}";
   s.op->newline() << "return 0;";
@@ -9031,7 +9051,7 @@ tracepoint_derived_probe_group::emit_module_decls (systemtap_session& s)
                           << " = __tracepoint_arg_" << used_args[j]->name << ";";
         }
       s.op->newline() << "(*probe->ph) (c);";
-      common_probe_entryfn_epilogue (s.op);
+      common_probe_entryfn_epilogue (s.op, true, s.suppress_handler_errors);
       s.op->newline(-1) << "}";
 
       // define the real tracepoint callback function
index 50b97ad7bf3f68584d4e45164fd35ce55113970a..c5fb30cb45451fe09539329a553321567cbfec0a 100644 (file)
--- a/tapsets.h
+++ b/tapsets.h
@@ -21,7 +21,7 @@ std::string common_probe_init (derived_probe* p);
 void common_probe_entryfn_prologue (translator_output* o, std::string statestr,
                                    std::string probe, std::string probe_type,
                                    bool overload_processing = true);
-void common_probe_entryfn_epilogue (translator_output* o, bool overload_processing = true);
+void common_probe_entryfn_epilogue (translator_output* o, bool overload_processing, bool suppress_handler_errors);
 
 void register_tapset_been(systemtap_session& sess);
 void register_tapset_itrace(systemtap_session& sess);
This page took 0.047507 seconds and 5 git commands to generate.