diff --git a/CMakeLists.txt b/CMakeLists.txt index c206719..cf789b9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -168,6 +168,8 @@ set(SOURCE_FILES src/compat/alloc.h src/compat/processor.c src/compat/processor.h + src/compat/kill.c + src/compat/kill.h src/io/redirect.c src/io/event.c src/io/event.h diff --git a/src/compat/kill.c b/src/compat/kill.c new file mode 100644 index 0000000..d87a08f --- /dev/null +++ b/src/compat/kill.c @@ -0,0 +1,88 @@ +/* + * The MIT License (MIT) + * + * Copyright © 2015-2016 Franklin "Snaipe" Mathieu + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include "kill.h" +#include "internal.h" +#include "criterion/logging.h" +#include "core/report.h" +#include "core/stats.h" +#include "io/event.h" +#include "io/output.h" +#include +#include + +static INLINE void nothing(void) {} + +#ifdef VANILLA_WIN32 +static HANDLE cr_job; +#else +static void handle_sigterm(int signum) { + assert(signum == SIGTERM); + + kill(-getpid(), SIGTERM); + _exit(1); +} +#endif + +void setup_parent_job(void) { +#ifdef VANILLA_WIN32 + // Put runner in its own job + SECURITY_ATTRIBUTES attr = {}; + cr_job = CreateJobObject(&attr, NULL); + if (!AssignProcessToJobObject(cr_job, GetCurrentProcess())) + abort(); +#else + // Put runner in its own group + setpgid(0, 0); + + // Setup termination handlers + sigset_t block_mask; + sigemptyset (&block_mask); + sigaddset (&block_mask, SIGINT); + sigaddset (&block_mask, SIGQUIT); + sigaddset (&block_mask, SIGTSTP); + + struct sigaction sa = { + .sa_handler = handle_sigterm, + .sa_mask = block_mask, + }; + sigaction(SIGTERM, &sa, NULL); +#endif +} + +void cr_killall(void) { +#ifdef VANILLA_WIN32 + if (!TerminateJobObject(cr_job, 1)) + abort(); +#else + kill(getpid(), SIGTERM); +#endif +} + +void cr_terminate(struct criterion_global_stats *stats) { + report(POST_ALL, stats); + process_all_output(stats); + log(post_all, stats); + + cr_killall(); +} diff --git a/src/compat/kill.h b/src/compat/kill.h new file mode 100644 index 0000000..f239cb2 --- /dev/null +++ b/src/compat/kill.h @@ -0,0 +1,34 @@ +/* + * The MIT License (MIT) + * + * Copyright © 2015-2016 Franklin "Snaipe" Mathieu + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#ifndef COMPAT_KILL_H_ +# define COMPAT_KILL_H_ + +# include "posix.h" +# include "criterion/stats.h" + +void setup_parent_job(void); +void cr_killall(void); +void cr_terminate(struct criterion_global_stats *stats); + +#endif /* !COMPAT_KILL_H_ */ diff --git a/src/core/runner.c b/src/core/runner.c index 6f232e4..e080349 100644 --- a/src/core/runner.c +++ b/src/core/runner.c @@ -35,6 +35,7 @@ #include "compat/time.h" #include "compat/posix.h" #include "compat/processor.h" +#include "compat/kill.h" #include "string/i18n.h" #include "io/event.h" #include "io/output.h" @@ -270,6 +271,10 @@ static void handle_worker_terminated(struct event *ev, } } } + + if (ctx->test_stats->failed && criterion_options.fail_fast) { + cr_terminate(ctx->stats); + } } static void handle_event(struct event *ev) { @@ -357,6 +362,8 @@ struct criterion_test_set *criterion_initialize(void) { criterion_register_output_provider("xml", xml_report); criterion_register_output_provider("json", json_report); + setup_parent_job(); + return criterion_init(); } diff --git a/test/cram/fail-fast.t b/test/cram/fail-fast.t index 9e0ee0a..5143440 100644 --- a/test/cram/fail-fast.t +++ b/test/cram/fail-fast.t @@ -1,7 +1,21 @@ Testing --fail-fast $ simple.c.bin --fail-fast --verbose + [\x1b[0;34m----\x1b[0m] Criterion v2.2.0 (esc) + [\x1b[0;34m====\x1b[0m] Running \x1b[0;34m2\x1b[0m tests from \x1b[0;33mmisc\x1b[0m: (esc) + [\x1b[0;34mRUN \x1b[0m] misc::failing (esc) + [\x1b[0;34m----\x1b[0m] \x1b[0;1msimple.c\x1b[0m:\x1b[0;31m4\x1b[0m: Assertion failed: The expression 0 is false. (esc) + [\x1b[0;31mFAIL\x1b[0m] misc::failing (esc) + [\x1b[0;34m====\x1b[0m] \x1b[0;1mSynthesis: Tested: \x1b[0;34m1\x1b[0;1m | Passing: \x1b[0;32m0\x1b[0;1m | Failing: \x1b[0;31m1\x1b[0;1m | Crashing: \x1b[0;31m0\x1b[0;1m \x1b[0m (esc) + [1] Testing CRITERION_FAIL_FAST $ CRITERION_FAIL_FAST=1 simple.c.bin --verbose + [\x1b[0;34m----\x1b[0m] Criterion v2.2.0 (esc) + [\x1b[0;34m====\x1b[0m] Running \x1b[0;34m2\x1b[0m tests from \x1b[0;33mmisc\x1b[0m: (esc) + [\x1b[0;34mRUN \x1b[0m] misc::failing (esc) + [\x1b[0;34m----\x1b[0m] \x1b[0;1msimple.c\x1b[0m:\x1b[0;31m4\x1b[0m: Assertion failed: The expression 0 is false. (esc) + [\x1b[0;31mFAIL\x1b[0m] misc::failing (esc) + [\x1b[0;34m====\x1b[0m] \x1b[0;1mSynthesis: Tested: \x1b[0;34m1\x1b[0;1m | Passing: \x1b[0;32m0\x1b[0;1m | Failing: \x1b[0;31m1\x1b[0;1m | Crashing: \x1b[0;31m0\x1b[0;1m \x1b[0m (esc) + [1]