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@xxxxxxxxxxxxxxxxxxx> > Cc: Shengyu Li <shengyu.li.evgeny@xxxxxxxxx> > 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@xxxxxxxxxxx> > Link: https://lore.kernel.org/r/20240426172252.1862930-4-mic@xxxxxxxxxxx Reviewed-by: Kees Cook <keescook@xxxxxxxxxxxx> -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); \ > + *teardown = false; \ > memset(&self, 0, sizeof(FIXTURE_DATA(fixture_name))); \ > if (setjmp(_metadata->env) == 0) { \ > /* Use the same _metadata. */ \ > @@ -400,15 +403,16 @@ > _metadata->exit_code = KSFT_FAIL; \ > } \ > } \ > - else \ > - jmp = true; \ > if (child == 0) { \ > - 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); \ > + munmap(teardown, sizeof(*teardown)); \ > if (!WIFEXITED(status) && WIFSIGNALED(status)) \ > /* Forward signal to __wait_for_test(). */ \ > kill(getpid(), WTERMSIG(status)); \ > -- > 2.44.0 > -- Kees Cook