Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

selftests: harness: Stop using setjmp()/longjmp()

Usage of longjmp() was added to ensure that teardown is always run in
commit 63e6b2a42342 ("selftests/harness: Run TEARDOWN for ASSERT failures")
However instead of calling longjmp() to the teardown handler it is easier to
just call the teardown handler directly from __bail().
Any potential duplicate teardown invocations are harmless as the actual
handler will only ever be executed once since
commit fff37bd32c76 ("selftests/harness: Fix fixture teardown").

Additionally this removes a incompatibility with nolibc,
which does not support setjmp()/longjmp().

Signed-off-by: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
Acked-by: Shuah Khan <skhan@linuxfoundation.org>
Link: https://lore.kernel.org/r/20250505-nolibc-kselftest-harness-v4-12-ee4dd5257135@linutronix.de
Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>

authored by

Thomas Weißschuh and committed by
Thomas Weißschuh
869c7889 f46ddc2c

+15 -30
+15 -30
tools/testing/selftests/kselftest_harness.h
··· 67 67 #include <sys/types.h> 68 68 #include <sys/wait.h> 69 69 #include <unistd.h> 70 - #include <setjmp.h> 71 70 72 71 #include "kselftest.h" 73 72 ··· 177 178 struct __test_metadata *_metadata, \ 178 179 struct __fixture_variant_metadata __attribute__((unused)) *variant) \ 179 180 { \ 180 - if (setjmp(_metadata->env) == 0) \ 181 - test_name(_metadata); \ 182 - __test_check_assert(_metadata); \ 181 + test_name(_metadata); \ 183 182 } \ 184 183 static struct __test_metadata _##test_name##_object = \ 185 184 { .name = #test_name, \ ··· 422 425 } \ 423 426 _metadata->variant = variant->data; \ 424 427 _metadata->self = self; \ 425 - if (setjmp(_metadata->env) == 0) { \ 426 - /* _metadata and potentially self are shared with all forks. */ \ 427 - child = fork(); \ 428 - if (child == 0) { \ 429 - fixture_name##_setup(_metadata, self, variant->data); \ 430 - /* Let setup failure terminate early. */ \ 431 - if (_metadata->exit_code) \ 432 - _exit(0); \ 433 - *_metadata->no_teardown = false; \ 434 - fixture_name##_##test_name(_metadata, self, variant->data); \ 435 - } else if (child < 0 || child != waitpid(child, &status, 0)) { \ 436 - ksft_print_msg("ERROR SPAWNING TEST GRANDCHILD\n"); \ 437 - _metadata->exit_code = KSFT_FAIL; \ 438 - } \ 439 - } \ 428 + /* _metadata and potentially self are shared with all forks. */ \ 429 + child = fork(); \ 440 430 if (child == 0) { \ 431 + fixture_name##_setup(_metadata, self, variant->data); \ 432 + /* Let setup failure terminate early. */ \ 433 + if (_metadata->exit_code) \ 434 + _exit(0); \ 435 + *_metadata->no_teardown = false; \ 436 + fixture_name##_##test_name(_metadata, self, variant->data); \ 441 437 _metadata->teardown_fn(false, _metadata, self, variant->data); \ 442 438 _exit(0); \ 439 + } else if (child < 0 || child != waitpid(child, &status, 0)) { \ 440 + ksft_print_msg("ERROR SPAWNING TEST GRANDCHILD\n"); \ 441 + _metadata->exit_code = KSFT_FAIL; \ 443 442 } \ 444 443 _metadata->teardown_fn(true, _metadata, self, variant->data); \ 445 444 munmap(_metadata->no_teardown, sizeof(*_metadata->no_teardown)); \ ··· 449 456 /* Forward signal to __wait_for_test(). */ \ 450 457 kill(getpid(), WTERMSIG(status)); \ 451 458 } \ 452 - __test_check_assert(_metadata); \ 453 459 } \ 454 460 static void wrapper_##fixture_name##_##test_name##_teardown( \ 455 461 bool in_parent, struct __test_metadata *_metadata, \ ··· 919 927 int timeout; /* seconds to wait for test timeout */ 920 928 bool aborted; /* stopped test due to failed ASSERT */ 921 929 bool *no_teardown; /* fixture needs teardown */ 922 - jmp_buf env; /* for exiting out of test early */ 923 930 void *self; 924 931 const void *variant; 925 932 struct __test_results *results; ··· 954 963 { 955 964 /* if this is ASSERT, return immediately. */ 956 965 if (for_realz) { 957 - t->aborted = true; 958 - longjmp(t->env, 1); 966 + if (t->teardown_fn) 967 + t->teardown_fn(false, t, t->self, t->variant); 968 + abort(); 959 969 } 960 970 /* otherwise, end the for loop and continue. */ 961 971 return 0; 962 - } 963 - 964 - static inline void __test_check_assert(struct __test_metadata *t) 965 - { 966 - if (t->aborted) 967 - abort(); 968 972 } 969 973 970 974 static void __wait_for_test(struct __test_metadata *t) ··· 1194 1208 t->trigger = 0; 1195 1209 t->aborted = false; 1196 1210 t->no_teardown = NULL; 1197 - memset(t->env, 0, sizeof(t->env)); 1198 1211 memset(t->results->reason, 0, sizeof(t->results->reason)); 1199 1212 1200 1213 snprintf(test_name, sizeof(test_name), "%s%s%s.%s",