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 <[email protected]> > Cc: Shengyu Li <[email protected]> > 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 <[email protected]> > Link: https://lore.kernel.org/r/[email protected] Reviewed-by: Kees Cook <[email protected]> -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
