diff --git a/src/client/crash_handler/crash_handler.c b/src/client/crash_handler/crash_handler.c index a59b3037..22990412 100644 --- a/src/client/crash_handler/crash_handler.c +++ b/src/client/crash_handler/crash_handler.c @@ -434,6 +434,7 @@ int crash_handler_install(int global_rank, int ldcsid_in) sigaddset(&sa.sa_mask, SIGABRT); const int sigs[] = { SIGSEGV, SIGBUS, SIGFPE, SIGILL, SIGABRT }; + crash_sigchain_activate(); for (size_t i = 0; i < sizeof(sigs) / sizeof(sigs[0]); i++) { /* If a signal handler was already installed by the time Spindle registers its signal handler, we save it to use in diff --git a/src/client/crash_handler/crash_sigchain.c b/src/client/crash_handler/crash_sigchain.c index 7e4351e5..c9de0f33 100644 --- a/src/client/crash_handler/crash_sigchain.c +++ b/src/client/crash_handler/crash_sigchain.c @@ -72,8 +72,18 @@ struct app_disposition { static const int OWNED_SIGS[] = { SIGSEGV, SIGBUS, SIGFPE, SIGILL, SIGABRT }; +/* Set once the crash handler has installed its handlers. */ +static int sigchain_active = 0; + +void crash_sigchain_activate(void) +{ + sigchain_active = 1; +} + int crash_sigchain_is_owned(int sig) { + if (!sigchain_active) + return 0; for (size_t i = 0; i < sizeof(OWNED_SIGS) / sizeof(OWNED_SIGS[0]); i++) { if (OWNED_SIGS[i] == sig) return 1; diff --git a/src/client/crash_handler/crash_sigchain.h b/src/client/crash_handler/crash_sigchain.h index d6d2fa39..273dcfaf 100644 --- a/src/client/crash_handler/crash_sigchain.h +++ b/src/client/crash_handler/crash_sigchain.h @@ -26,6 +26,7 @@ Place, Suite 330, Boston, MA 02111-1307 USA #define CRASH_CHAIN_HANDLED 1 /* application handler ran and returned */ #define CRASH_CHAIN_IGNORED 2 /* application disposition is SIG_IGN */ +void crash_sigchain_activate(void); int crash_sigchain_is_owned(int sig); void crash_sigchain_register_existing_handler(int sig, const struct sigaction *handler_old); int crash_sigchain_chain_to_app(int sig, siginfo_t *info, void *ucontext); diff --git a/testsuite/run_crash_tests_template.sh b/testsuite/run_crash_tests_template.sh index 1e8e2bf9..03b04379 100755 --- a/testsuite/run_crash_tests_template.sh +++ b/testsuite/run_crash_tests_template.sh @@ -35,6 +35,7 @@ die() { echo "FAIL: $*" >&2; exit 1; } # flags (comma-separated): "multi-rank" skips the mode on a single rank; # "clean" expects the test to NOT crash; "altstack" runs the mode with # --crash-altstack; "nofollowfork" runs it with --follow-fork=false; +# "nocrashhandler" runs it without the crash handler; # "forkchild" means rows may come from fork or exec children of a rank. # top_frame_regex: regex that should match the top frame in produced coredumps. # Note that all threads will be checked, so in multithreaded examples the regex should @@ -70,6 +71,7 @@ CRASH_TESTS=( 'safepoint-fix-write ; 0 ; 0 ; clean ; -' 'safepoint-fix-write-altstack ; 0 ; 0 ; clean,altstack ; - ; ; ; safepoint-fix-write' 'safepoint-longjmp ; 0 ; 0 ; clean ; -' + 'safepoint-nocrashhandler ; 0 ; 0 ; clean,nocrashhandler ; - ; ; ; safepoint' 'safepoint-span-read ; 0 ; 0 ; clean ; -' 'safepoint-span-write ; 0 ; 0 ; clean ; -' 'safepoint-span-bad-read ; 1 ; N ; ; do_safepoint_span_bad_read' @@ -266,6 +268,11 @@ launch() { cmdline_opts="$cmdline_opts --follow-fork=false" flux_opts+=(-o spindle.follow-fork=no) fi + if has_flag "$mode" nocrashhandler; then + cmdline_opts="" + flux_opts=(-o spindle) + export SPINDLE_NO_CRASH_DEDUP=1 + fi ulimit -c unlimited # Make libcrashfuncs.so visible to dlopen() from the mode's scratch dir. export LD_LIBRARY_PATH="$TESTDIR${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}" @@ -290,7 +297,7 @@ launch() { ;; slurm-plugin) salloc -N"$NODES" -n"$NODES" \ - srun --spindle="$cmdline_opts" \ + srun "--spindle${cmdline_opts:+=$cmdline_opts}" \ "$binary" --crash-mode "$crash_mode" ;; esac