Skip to content

Commit 73a3cde

Browse files
committed
selftests: harness: Implement test timeouts through pidfd
Make the kselftest harness compatible with nolibc which does not implement signals by replacing the signal logic with pidfds. The code also becomes simpler. Signed-off-by: Thomas Weißschuh <[email protected]> Acked-by: Shuah Khan <[email protected]> Link: https://lore.kernel.org/r/20250505-nolibc-kselftest-harness-v4-7-ee4dd5257135@linutronix.de Signed-off-by: Thomas Weißschuh <[email protected]>
1 parent 67ee526 commit 73a3cde

File tree

1 file changed

+25
-47
lines changed

1 file changed

+25
-47
lines changed

tools/testing/selftests/kselftest_harness.h

Lines changed: 25 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@
5656
#include <asm/types.h>
5757
#include <ctype.h>
5858
#include <errno.h>
59+
#include <linux/unistd.h>
60+
#include <poll.h>
5961
#include <stdbool.h>
6062
#include <stdint.h>
6163
#include <stdio.h>
@@ -914,7 +916,6 @@ struct __test_metadata {
914916
int exit_code;
915917
int trigger; /* extra handler after the evaluation */
916918
int timeout; /* seconds to wait for test timeout */
917-
bool timed_out; /* did this test timeout instead of exiting? */
918919
bool aborted; /* stopped test due to failed ASSERT */
919920
bool setup_completed; /* did setup finish? */
920921
jmp_buf env; /* for exiting out of test early */
@@ -964,75 +965,52 @@ static inline void __test_check_assert(struct __test_metadata *t)
964965
abort();
965966
}
966967

967-
struct __test_metadata *__active_test;
968-
static void __timeout_handler(int sig, siginfo_t *info, void *ucontext)
969-
{
970-
struct __test_metadata *t = __active_test;
971-
972-
/* Sanity check handler execution environment. */
973-
if (!t) {
974-
fprintf(TH_LOG_STREAM,
975-
"# no active test in SIGALRM handler!?\n");
976-
abort();
977-
}
978-
if (sig != SIGALRM || sig != info->si_signo) {
979-
fprintf(TH_LOG_STREAM,
980-
"# %s: SIGALRM handler caught signal %d!?\n",
981-
t->name, sig != SIGALRM ? sig : info->si_signo);
982-
abort();
983-
}
984-
985-
t->timed_out = true;
986-
/* signal process group */
987-
kill(-(t->pid), SIGKILL);
988-
}
989-
990968
static void __wait_for_test(struct __test_metadata *t)
991969
{
992-
struct sigaction action = {
993-
.sa_sigaction = __timeout_handler,
994-
.sa_flags = SA_SIGINFO,
995-
};
996-
struct sigaction saved_action;
997970
/*
998971
* Sets status so that WIFEXITED(status) returns true and
999972
* WEXITSTATUS(status) returns KSFT_FAIL. This safe default value
1000973
* should never be evaluated because of the waitpid(2) check and
1001-
* SIGALRM handling.
974+
* timeout handling.
1002975
*/
1003976
int status = KSFT_FAIL << 8;
1004-
int child;
977+
struct pollfd poll_child;
978+
int ret, child, childfd;
979+
bool timed_out = false;
1005980

1006-
if (sigaction(SIGALRM, &action, &saved_action)) {
981+
childfd = syscall(__NR_pidfd_open, t->pid, 0);
982+
if (childfd == -1) {
1007983
t->exit_code = KSFT_FAIL;
1008984
fprintf(TH_LOG_STREAM,
1009-
"# %s: unable to install SIGALRM handler\n",
985+
"# %s: unable to open pidfd\n",
1010986
t->name);
1011987
return;
1012988
}
1013-
__active_test = t;
1014-
t->timed_out = false;
1015-
alarm(t->timeout);
1016-
child = waitpid(t->pid, &status, 0);
1017-
if (child == -1 && errno != EINTR) {
989+
990+
poll_child.fd = childfd;
991+
poll_child.events = POLLIN;
992+
ret = poll(&poll_child, 1, t->timeout * 1000);
993+
if (ret == -1) {
1018994
t->exit_code = KSFT_FAIL;
1019995
fprintf(TH_LOG_STREAM,
1020-
"# %s: Failed to wait for PID %d (errno: %d)\n",
1021-
t->name, t->pid, errno);
996+
"# %s: unable to wait on child pidfd\n",
997+
t->name);
1022998
return;
999+
} else if (ret == 0) {
1000+
timed_out = true;
1001+
/* signal process group */
1002+
kill(-(t->pid), SIGKILL);
10231003
}
1024-
1025-
alarm(0);
1026-
if (sigaction(SIGALRM, &saved_action, NULL)) {
1004+
child = waitpid(t->pid, &status, WNOHANG);
1005+
if (child == -1 && errno != EINTR) {
10271006
t->exit_code = KSFT_FAIL;
10281007
fprintf(TH_LOG_STREAM,
1029-
"# %s: unable to uninstall SIGALRM handler\n",
1030-
t->name);
1008+
"# %s: Failed to wait for PID %d (errno: %d)\n",
1009+
t->name, t->pid, errno);
10311010
return;
10321011
}
1033-
__active_test = NULL;
10341012

1035-
if (t->timed_out) {
1013+
if (timed_out) {
10361014
t->exit_code = KSFT_FAIL;
10371015
fprintf(TH_LOG_STREAM,
10381016
"# %s: Test terminated by timeout\n", t->name);

0 commit comments

Comments
 (0)