Make the 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 <thomas.weisssc...@linutronix.de>
---
 tools/testing/selftests/kselftest_harness.h | 72 ++++++++++-------------------
 1 file changed, 25 insertions(+), 47 deletions(-)

diff --git a/tools/testing/selftests/kselftest_harness.h 
b/tools/testing/selftests/kselftest_harness.h
index 
bf5ffc594a4a864d2e8bb6f47c29fa56d58919d9..d265b45c86d03c6f854047138ee8dc19dcc7a4d9
 100644
--- a/tools/testing/selftests/kselftest_harness.h
+++ b/tools/testing/selftests/kselftest_harness.h
@@ -65,6 +65,8 @@
 #include <asm/types.h>
 #include <ctype.h>
 #include <errno.h>
+#include <linux/unistd.h>
+#include <poll.h>
 #include <sys/mman.h>
 #include <sys/types.h>
 #include <sys/wait.h>
@@ -918,7 +920,6 @@ struct __test_metadata {
        int exit_code;
        int trigger; /* extra handler after the evaluation */
        int timeout;    /* seconds to wait for test timeout */
-       bool timed_out; /* did this test timeout instead of exiting? */
        bool aborted;   /* stopped test due to failed ASSERT */
        bool setup_completed; /* did setup finish? */
        jmp_buf env;    /* for exiting out of test early */
@@ -968,75 +969,52 @@ static inline void __test_check_assert(struct 
__test_metadata *t)
                abort();
 }
 
-struct __test_metadata *__active_test;
-static void __timeout_handler(int sig, siginfo_t *info, void *ucontext)
-{
-       struct __test_metadata *t = __active_test;
-
-       /* Sanity check handler execution environment. */
-       if (!t) {
-               fprintf(TH_LOG_STREAM,
-                       "# no active test in SIGALRM handler!?\n");
-               abort();
-       }
-       if (sig != SIGALRM || sig != info->si_signo) {
-               fprintf(TH_LOG_STREAM,
-                       "# %s: SIGALRM handler caught signal %d!?\n",
-                       t->name, sig != SIGALRM ? sig : info->si_signo);
-               abort();
-       }
-
-       t->timed_out = true;
-       /* signal process group */
-       kill(-(t->pid), SIGKILL);
-}
-
 static void __wait_for_test(struct __test_metadata *t)
 {
-       struct sigaction action = {
-               .sa_sigaction = __timeout_handler,
-               .sa_flags = SA_SIGINFO,
-       };
-       struct sigaction saved_action;
        /*
         * Sets status so that WIFEXITED(status) returns true and
         * WEXITSTATUS(status) returns KSFT_FAIL.  This safe default value
         * should never be evaluated because of the waitpid(2) check and
-        * SIGALRM handling.
+        * timeout handling.
         */
        int status = KSFT_FAIL << 8;
-       int child;
+       struct pollfd poll_child;
+       int ret, child, childfd;
+       bool timed_out = false;
 
-       if (sigaction(SIGALRM, &action, &saved_action)) {
+       childfd = syscall(__NR_pidfd_open, t->pid, 0);
+       if (childfd == -1) {
                t->exit_code = KSFT_FAIL;
                fprintf(TH_LOG_STREAM,
-                       "# %s: unable to install SIGALRM handler\n",
+                       "# %s: unable to open pidfd\n",
                        t->name);
                return;
        }
-       __active_test = t;
-       t->timed_out = false;
-       alarm(t->timeout);
-       child = waitpid(t->pid, &status, 0);
-       if (child == -1 && errno != EINTR) {
+
+       poll_child.fd = childfd;
+       poll_child.events = POLLIN;
+       ret = poll(&poll_child, 1, t->timeout * 1000);
+       if (ret == -1) {
                t->exit_code = KSFT_FAIL;
                fprintf(TH_LOG_STREAM,
-                       "# %s: Failed to wait for PID %d (errno: %d)\n",
-                       t->name, t->pid, errno);
+                       "# %s: unable to wait on child pidfd\n",
+                       t->name);
                return;
+       } else if (ret == 0) {
+               timed_out = true;
+               /* signal process group */
+               kill(-(t->pid), SIGKILL);
        }
-
-       alarm(0);
-       if (sigaction(SIGALRM, &saved_action, NULL)) {
+       child = waitpid(t->pid, &status, WNOHANG);
+       if (child == -1 && errno != EINTR) {
                t->exit_code = KSFT_FAIL;
                fprintf(TH_LOG_STREAM,
-                       "# %s: unable to uninstall SIGALRM handler\n",
-                       t->name);
+                       "# %s: Failed to wait for PID %d (errno: %d)\n",
+                       t->name, t->pid, errno);
                return;
        }
-       __active_test = NULL;
 
-       if (t->timed_out) {
+       if (timed_out) {
                t->exit_code = KSFT_FAIL;
                fprintf(TH_LOG_STREAM,
                        "# %s: Test terminated by timeout\n", t->name);

-- 
2.48.1


Reply via email to