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);
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,
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;
" 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"
#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 },
{ "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:",
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;
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).
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) << "}";
}
// 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) << "}";
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;
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) << "}";
}
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;";
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;";
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) << "}";
}
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) << "}";
}
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
// 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) << "}";
// 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);
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)";
// 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\");";
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 ();";
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) << "}";
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) << "}";
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) {";
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();
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) << "}";
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) << "}";
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;";
<< " = __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
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);