On Fri, Apr 26, 2024 at 07:22:50PM +0200, Mickaël Salaün wrote:
Make sure fixture teardowns are run when test cases failed, including when _metadata->teardown_parent is set to true.
Make sure only one fixture teardown is run per test case, handling the case where the test child forks.
I had to go look up __sync_bool_compare_and_swap(). :)
Cc: Shuah Khan skhan@linuxfoundation.org Cc: Shengyu Li shengyu.li.evgeny@gmail.com Fixes: 72d7cb5c190b ("selftests/harness: Prevent infinite loop due to Assert in FIXTURE_TEARDOWN") Fixes: 0710a1a73fb4 ("selftests/harness: Merge TEST_F_FORK() into TEST_F()") Signed-off-by: Mickaël Salaün mic@digikod.net Link: https://lore.kernel.org/r/20240426172252.1862930-4-mic@digikod.net
Reviewed-by: Kees Cook keescook@chromium.org
-Kees
tools/testing/selftests/kselftest_harness.h | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-)
diff --git a/tools/testing/selftests/kselftest_harness.h b/tools/testing/selftests/kselftest_harness.h index ba3ddeda24bf..73491efbae9e 100644 --- a/tools/testing/selftests/kselftest_harness.h +++ b/tools/testing/selftests/kselftest_harness.h @@ -383,7 +383,10 @@ FIXTURE_DATA(fixture_name) self; \ pid_t child = 1; \ int status = 0; \
bool jmp = false; \
/* Makes sure there is only one teardown, even when child forks again. */ \
bool *teardown = mmap(NULL, sizeof(*teardown), \
PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0); \
memset(&self, 0, sizeof(FIXTURE_DATA(fixture_name))); \ if (setjmp(_metadata->env) == 0) { \ /* Use the same _metadata. */ \*teardown = false; \
@@ -400,15 +403,16 @@ _metadata->exit_code = KSFT_FAIL; \ } \ } \
else \
if (child == 0) { \jmp = true; \
if (_metadata->setup_completed && !_metadata->teardown_parent && !jmp) \
if (_metadata->setup_completed && !_metadata->teardown_parent && \
} \__sync_bool_compare_and_swap(teardown, false, true)) \ fixture_name##_teardown(_metadata, &self, variant->data); \ _exit(0); \
if (_metadata->setup_completed && _metadata->teardown_parent) \
if (_metadata->setup_completed && _metadata->teardown_parent && \
__sync_bool_compare_and_swap(teardown, false, true)) \ fixture_name##_teardown(_metadata, &self, variant->data); \
if (!WIFEXITED(status) && WIFSIGNALED(status)) \ /* Forward signal to __wait_for_test(). */ \ kill(getpid(), WTERMSIG(status)); \munmap(teardown, sizeof(*teardown)); \
-- 2.44.0