2
0
mirror of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git synced 2025-09-04 20:19:47 +08:00

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

Usage of longjmp() was added to ensure that teardown is always run in
commit 63e6b2a423 ("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 fff37bd32c ("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>
This commit is contained in:
Thomas Weißschuh 2025-05-05 17:15:30 +02:00 committed by Thomas Weißschuh
parent f46ddc2cba
commit 869c788909

View File

@ -67,7 +67,6 @@
#include <sys/types.h> #include <sys/types.h>
#include <sys/wait.h> #include <sys/wait.h>
#include <unistd.h> #include <unistd.h>
#include <setjmp.h>
#include "kselftest.h" #include "kselftest.h"
@ -178,9 +177,7 @@
struct __test_metadata *_metadata, \ struct __test_metadata *_metadata, \
struct __fixture_variant_metadata __attribute__((unused)) *variant) \ struct __fixture_variant_metadata __attribute__((unused)) *variant) \
{ \ { \
if (setjmp(_metadata->env) == 0) \
test_name(_metadata); \ test_name(_metadata); \
__test_check_assert(_metadata); \
} \ } \
static struct __test_metadata _##test_name##_object = \ static struct __test_metadata _##test_name##_object = \
{ .name = #test_name, \ { .name = #test_name, \
@ -425,7 +422,6 @@
} \ } \
_metadata->variant = variant->data; \ _metadata->variant = variant->data; \
_metadata->self = self; \ _metadata->self = self; \
if (setjmp(_metadata->env) == 0) { \
/* _metadata and potentially self are shared with all forks. */ \ /* _metadata and potentially self are shared with all forks. */ \
child = fork(); \ child = fork(); \
if (child == 0) { \ if (child == 0) { \
@ -435,15 +431,12 @@
_exit(0); \ _exit(0); \
*_metadata->no_teardown = false; \ *_metadata->no_teardown = false; \
fixture_name##_##test_name(_metadata, self, variant->data); \ fixture_name##_##test_name(_metadata, self, variant->data); \
_metadata->teardown_fn(false, _metadata, self, variant->data); \
_exit(0); \
} else if (child < 0 || child != waitpid(child, &status, 0)) { \ } else if (child < 0 || child != waitpid(child, &status, 0)) { \
ksft_print_msg("ERROR SPAWNING TEST GRANDCHILD\n"); \ ksft_print_msg("ERROR SPAWNING TEST GRANDCHILD\n"); \
_metadata->exit_code = KSFT_FAIL; \ _metadata->exit_code = KSFT_FAIL; \
} \ } \
} \
if (child == 0) { \
_metadata->teardown_fn(false, _metadata, self, variant->data); \
_exit(0); \
} \
_metadata->teardown_fn(true, _metadata, self, variant->data); \ _metadata->teardown_fn(true, _metadata, self, variant->data); \
munmap(_metadata->no_teardown, sizeof(*_metadata->no_teardown)); \ munmap(_metadata->no_teardown, sizeof(*_metadata->no_teardown)); \
_metadata->no_teardown = NULL; \ _metadata->no_teardown = NULL; \
@ -456,7 +449,6 @@
/* Forward signal to __wait_for_test(). */ \ /* Forward signal to __wait_for_test(). */ \
kill(getpid(), WTERMSIG(status)); \ kill(getpid(), WTERMSIG(status)); \
} \ } \
__test_check_assert(_metadata); \
} \ } \
static void wrapper_##fixture_name##_##test_name##_teardown( \ static void wrapper_##fixture_name##_##test_name##_teardown( \
bool in_parent, struct __test_metadata *_metadata, \ bool in_parent, struct __test_metadata *_metadata, \
@ -927,7 +919,6 @@ struct __test_metadata {
int timeout; /* seconds to wait for test timeout */ int timeout; /* seconds to wait for test timeout */
bool aborted; /* stopped test due to failed ASSERT */ bool aborted; /* stopped test due to failed ASSERT */
bool *no_teardown; /* fixture needs teardown */ bool *no_teardown; /* fixture needs teardown */
jmp_buf env; /* for exiting out of test early */
void *self; void *self;
const void *variant; const void *variant;
struct __test_results *results; struct __test_results *results;
@ -963,19 +954,14 @@ static inline int __bail(int for_realz, struct __test_metadata *t)
{ {
/* if this is ASSERT, return immediately. */ /* if this is ASSERT, return immediately. */
if (for_realz) { if (for_realz) {
t->aborted = true; if (t->teardown_fn)
longjmp(t->env, 1); t->teardown_fn(false, t, t->self, t->variant);
abort();
} }
/* otherwise, end the for loop and continue. */ /* otherwise, end the for loop and continue. */
return 0; return 0;
} }
static inline void __test_check_assert(struct __test_metadata *t)
{
if (t->aborted)
abort();
}
static void __wait_for_test(struct __test_metadata *t) static void __wait_for_test(struct __test_metadata *t)
{ {
/* /*
@ -1208,7 +1194,6 @@ static void __run_test(struct __fixture_metadata *f,
t->trigger = 0; t->trigger = 0;
t->aborted = false; t->aborted = false;
t->no_teardown = NULL; t->no_teardown = NULL;
memset(t->env, 0, sizeof(t->env));
memset(t->results->reason, 0, sizeof(t->results->reason)); memset(t->results->reason, 0, sizeof(t->results->reason));
snprintf(test_name, sizeof(test_name), "%s%s%s.%s", snprintf(test_name, sizeof(test_name), "%s%s%s.%s",