diff options
author | fche <fche> | 2008-02-28 21:34:46 +0000 |
---|---|---|
committer | fche <fche> | 2008-02-28 21:34:46 +0000 |
commit | 49abf162fa91397b0c65d41f5c9af31ace4e6290 (patch) | |
tree | 45fe654102d6db99e627fe04f7cbfd78e9db12e1 | |
parent | 7e6c2d0bd81af35151167ca75fc1b7d20a9e9a7d (diff) | |
download | systemtap-steved-49abf162fa91397b0c65d41f5c9af31ace4e6290.tar.gz systemtap-steved-49abf162fa91397b0c65d41f5c9af31ace4e6290.tar.xz systemtap-steved-49abf162fa91397b0c65d41f5c9af31ace4e6290.zip |
PR5045: clean up after interrupts
2008-02-28 Frank Ch. Eigler <fche@elastic.org>
PR5045
* session.h (pending_interrupts): New global.
* main.cxx (handle_interrupts): New fn to handle SIGINT* etc.
* elaborate.cxx, translate.cxx, tapsets.cxx, main.cxx (*): Insert
pending_interrupts escape hatches inside potentially timetaking loops.
* buildrun.cxx: Don't deal with signals.
-rw-r--r-- | ChangeLog | 9 | ||||
-rw-r--r-- | buildrun.cxx | 5 | ||||
-rw-r--r-- | elaborate.cxx | 17 | ||||
-rw-r--r-- | main.cxx | 47 | ||||
-rw-r--r-- | session.h | 3 | ||||
-rw-r--r-- | tapsets.cxx | 6 | ||||
-rw-r--r-- | translate.cxx | 11 |
7 files changed, 82 insertions, 16 deletions
@@ -1,3 +1,12 @@ +2008-02-28 Frank Ch. Eigler <fche@elastic.org> + + PR5045 + * session.h (pending_interrupts): New global. + * main.cxx (handle_interrupts): New fn to handle SIGINT* etc. + * elaborate.cxx, translate.cxx, tapsets.cxx, main.cxx (*): Insert + pending_interrupts escape hatches inside potentially timetaking loops. + * buildrun.cxx: Don't deal with signals. + 2008-02-27 Frank Ch. Eigler <fche@elastic.org> PR5697 diff --git a/buildrun.cxx b/buildrun.cxx index 67836108..f3f29d49 100644 --- a/buildrun.cxx +++ b/buildrun.cxx @@ -16,7 +16,7 @@ #include <sstream> extern "C" { -#include "signal.h" +#include <signal.h> #include <sys/wait.h> #include <pwd.h> #include <sys/types.h> @@ -269,9 +269,6 @@ run_pass (systemtap_session& s) if (s.verbose>1) clog << "Running " << staprun_cmd << endl; - signal (SIGHUP, SIG_IGN); - signal (SIGINT, SIG_IGN); rc = system (staprun_cmd.c_str ()); - return rc; } diff --git a/elaborate.cxx b/elaborate.cxx index 7f4ccf35..75714102 100644 --- a/elaborate.cxx +++ b/elaborate.cxx @@ -344,6 +344,8 @@ match_node::find_and_build (systemtap_session& s, const match_key& subkey = i->first; match_node* subnode = i->second; + if (pending_interrupts) break; + if (match.globmatch(subkey)) { if (s.verbose > 2) @@ -627,6 +629,8 @@ derive_probes (systemtap_session& s, { for (unsigned i = 0; i < p->locations.size(); ++i) { + if (pending_interrupts) break; + probe_point *loc = p->locations[i]; try @@ -1070,6 +1074,7 @@ semantic_pass_symbols (systemtap_session& s) s.files.push_back (s.user_file); for (unsigned i = 0; i < s.files.size(); i++) { + if (pending_interrupts) break; stapfile* dome = s.files[i]; // Pass 1: add globals and functions to systemtap-session master list, @@ -1088,6 +1093,7 @@ semantic_pass_symbols (systemtap_session& s) for (unsigned i=0; i<dome->functions.size(); i++) { + if (pending_interrupts) break; functiondecl* fd = dome->functions[i]; try @@ -1107,6 +1113,7 @@ semantic_pass_symbols (systemtap_session& s) for (unsigned i=0; i<dome->probes.size(); i++) { + if (pending_interrupts) break; probe* p = dome->probes [i]; vector<derived_probe*> dps; @@ -1116,6 +1123,7 @@ semantic_pass_symbols (systemtap_session& s) for (unsigned j=0; j<dps.size(); j++) { + if (pending_interrupts) break; derived_probe* dp = dps[j]; s.probes.push_back (dp); dp->join_group (s); @@ -2025,6 +2033,8 @@ semantic_pass_optimize1 (systemtap_session& s) bool relaxed_p = false; while (! relaxed_p) { + if (pending_interrupts) break; + relaxed_p = true; // until proven otherwise semantic_pass_opt1 (s, relaxed_p); @@ -2052,6 +2062,7 @@ semantic_pass_optimize2 (systemtap_session& s) bool relaxed_p = false; while (! relaxed_p) { + if (pending_interrupts) break; relaxed_p = true; // until proven otherwise semantic_pass_opt5 (s, relaxed_p); @@ -2082,12 +2093,16 @@ semantic_pass_types (systemtap_session& s) // XXX: maybe convert to exception-based error signalling while (1) { + if (pending_interrupts) break; + iterations ++; ti.num_newly_resolved = 0; ti.num_still_unresolved = 0; for (unsigned j=0; j<s.functions.size(); j++) { + if (pending_interrupts) break; + functiondecl* fn = s.functions[j]; ti.current_probe = 0; ti.current_function = fn; @@ -2103,6 +2118,8 @@ semantic_pass_types (systemtap_session& s) for (unsigned j=0; j<s.probes.size(); j++) { + if (pending_interrupts) break; + derived_probe* pn = s.probes[j]; ti.current_function = 0; ti.current_probe = pn; @@ -29,6 +29,7 @@ extern "C" { #include <glob.h> #include <unistd.h> +#include <signal.h> #include <sys/utsname.h> #include <sys/times.h> #include <sys/time.h> @@ -185,6 +186,23 @@ printscript(systemtap_session& s, ostream& o) } } + +int pending_interrupts; + +extern "C" +void handle_interrupt (int /* sig */) +{ + pending_interrupts ++; + 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); + if (rc) /* Do nothing; we don't care if our last gasp went out. */ ; + _exit (1); + } +} + + int main (int argc, char * const argv []) { @@ -541,6 +559,13 @@ main (int argc, char * const argv []) // directory. s.translated_source = string(s.tmpdir) + "/" + s.module_name + ".c"; + // Set up our handler to catch routine signals, to allow clean + // and reasonably timely exit. + signal (SIGHUP, handle_interrupt); + signal (SIGPIPE, handle_interrupt); + signal (SIGINT, handle_interrupt); + signal (SIGTERM, handle_interrupt); + struct tms tms_before; times (& tms_before); struct timeval tv_before; @@ -616,8 +641,10 @@ main (int argc, char * const argv []) for (unsigned j=0; j<globbuf.gl_pathc; j++) { - // privilege only for /usr/share/systemtap? - + if (pending_interrupts) + break; + + // XXX: privilege only for /usr/share/systemtap? stapfile* f = parser::parse (s, globbuf.gl_pathv[j], true); if (f == 0) rc ++; @@ -683,7 +710,7 @@ main (int argc, char * const argv []) << "Try again with more '-v' (verbose) options." << endl; - if (rc || s.last_pass == 1) goto cleanup; + if (rc || s.last_pass == 1 || pending_interrupts) goto cleanup; times (& tms_before); gettimeofday (&tv_before, NULL); @@ -733,14 +760,14 @@ main (int argc, char * const argv []) { // If our last pass isn't 5, we're done (since passes 3 and // 4 just generate what we just pulled out of the cache). - if (s.last_pass < 5) goto cleanup; + if (s.last_pass < 5 || pending_interrupts) goto cleanup; // Short-circuit to pass 5. goto pass_5; } } - if (rc || s.last_pass == 2) goto cleanup; + if (rc || s.last_pass == 2 || pending_interrupts) goto cleanup; // PASS 3: TRANSLATION @@ -769,7 +796,7 @@ main (int argc, char * const argv []) << "Try again with more '-v' (verbose) options." << endl; - if (rc || s.last_pass == 3) goto cleanup; + if (rc || s.last_pass == 3 || pending_interrupts) goto cleanup; // PASS 4: COMPILATION times (& tms_before); @@ -799,7 +826,7 @@ main (int argc, char * const argv []) add_to_cache(s); // Copy module to the current directory. - if (save_module) + if (save_module && !pending_interrupts) { string module_src_path = s.tmpdir + "/" + s.module_name + ".ko"; string module_dest_path = s.module_name + ".ko"; @@ -813,7 +840,7 @@ main (int argc, char * const argv []) } } - if (rc || s.last_pass == 4) goto cleanup; + if (rc || s.last_pass == 4 || pending_interrupts) goto cleanup; // PASS 5: RUN @@ -841,7 +868,7 @@ pass_5: cleanup: // update the database information - if (!rc && s.tapset_compile_coverage) { + if (!rc && s.tapset_compile_coverage && !pending_interrupts) { #ifdef HAVE_LIBSQLITE3 update_coverage_db(s); #else @@ -867,5 +894,5 @@ pass_5: } } - return rc ? EXIT_FAILURE : EXIT_SUCCESS; + return (rc||pending_interrupts) ? EXIT_FAILURE : EXIT_SUCCESS; } @@ -160,4 +160,7 @@ struct systemtap_session }; +// global counter of SIGINT/SIGTERM's received +extern int pending_interrupts; + #endif // SESSION_H diff --git a/tapsets.cxx b/tapsets.cxx index c5ed6ea1..52c14024 100644 --- a/tapsets.cxx +++ b/tapsets.cxx @@ -827,6 +827,7 @@ struct dwflpp ptrdiff_t off = 0; do { + if (pending_interrupts) return; off = dwfl_getmodules (dwfl, module_caching_callback, & module_cache, off); } @@ -837,6 +838,7 @@ struct dwflpp // Traverse the cache. for (unsigned i = 0; i < module_cache.size(); i++) { + if (pending_interrupts) return; module_cache_entry& it = module_cache[i]; int rc = callback (it.mod, 0, it.name, it.addr, data); if (rc != DWARF_CB_OK) break; @@ -868,6 +870,7 @@ struct dwflpp Dwarf_Off noff; while (dwarf_nextcu (dw, off, &noff, &cuhl, NULL, NULL, NULL) == 0) { + if (pending_interrupts) return; Dwarf_Die die_mem; Dwarf_Die *die; die = dwarf_offdie (dw, off + cuhl, &die_mem); @@ -878,6 +881,7 @@ struct dwflpp for (unsigned i = 0; i < v->size(); i++) { + if (pending_interrupts) return; Dwarf_Die die = v->at(i); int rc = (*callback)(& die, data); if (rc != DWARF_CB_OK) break; @@ -1057,6 +1061,7 @@ struct dwflpp { for (size_t i = 0; i < nsrcs; ++i) { + if (pending_interrupts) return; if (srcsp [i]) // skip over mismatched lines callback (srcsp[i], data); } @@ -3012,6 +3017,7 @@ static int query_cu (Dwarf_Die * cudie, void * arg) { dwarf_query * q = static_cast<dwarf_query *>(arg); + if (pending_interrupts) return DWARF_CB_ABORT; try { diff --git a/translate.cxx b/translate.cxx index fefb0c8f..855a8e93 100644 --- a/translate.cxx +++ b/translate.cxx @@ -4471,18 +4471,21 @@ translate_pass (systemtap_session& s) s.op->newline(1); for (unsigned i=0; i<s.globals.size(); i++) { + if (pending_interrupts) return 1; s.up->emit_global_init (s.globals[i]); } s.op->newline(-1) << "};"; for (unsigned i=0; i<s.functions.size(); i++) { + if (pending_interrupts) return 1; s.op->newline(); s.up->emit_functionsig (s.functions[i]); } for (unsigned i=0; i<s.functions.size(); i++) { + if (pending_interrupts) return 1; s.op->newline(); s.up->emit_function (s.functions[i]); } @@ -4492,12 +4495,16 @@ translate_pass (systemtap_session& s) // emit_locks()/emit_unlocks(). for (unsigned i=0; i<s.probes.size(); i++) { - if (s.probes[i]->needs_global_locks()) + if (pending_interrupts) return 1; + if (s.probes[i]->needs_global_locks()) s.probes[i]->body->visit (&cup.vcv_needs_global_locks); } for (unsigned i=0; i<s.probes.size(); i++) - s.up->emit_probe (s.probes[i]); + { + if (pending_interrupts) return 1; + s.up->emit_probe (s.probes[i]); + } s.op->newline(); s.up->emit_module_init (); |