|
56 | 56 | #include <asm/types.h> |
57 | 57 | #include <ctype.h> |
58 | 58 | #include <errno.h> |
| 59 | +#include <linux/unistd.h> |
| 60 | +#include <poll.h> |
59 | 61 | #include <stdbool.h> |
60 | 62 | #include <stdint.h> |
61 | 63 | #include <stdio.h> |
@@ -914,7 +916,6 @@ struct __test_metadata { |
914 | 916 | int exit_code; |
915 | 917 | int trigger; /* extra handler after the evaluation */ |
916 | 918 | int timeout; /* seconds to wait for test timeout */ |
917 | | - bool timed_out; /* did this test timeout instead of exiting? */ |
918 | 919 | bool aborted; /* stopped test due to failed ASSERT */ |
919 | 920 | bool setup_completed; /* did setup finish? */ |
920 | 921 | jmp_buf env; /* for exiting out of test early */ |
@@ -964,75 +965,52 @@ static inline void __test_check_assert(struct __test_metadata *t) |
964 | 965 | abort(); |
965 | 966 | } |
966 | 967 |
|
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 | | - |
990 | 968 | static void __wait_for_test(struct __test_metadata *t) |
991 | 969 | { |
992 | | - struct sigaction action = { |
993 | | - .sa_sigaction = __timeout_handler, |
994 | | - .sa_flags = SA_SIGINFO, |
995 | | - }; |
996 | | - struct sigaction saved_action; |
997 | 970 | /* |
998 | 971 | * Sets status so that WIFEXITED(status) returns true and |
999 | 972 | * WEXITSTATUS(status) returns KSFT_FAIL. This safe default value |
1000 | 973 | * should never be evaluated because of the waitpid(2) check and |
1001 | | - * SIGALRM handling. |
| 974 | + * timeout handling. |
1002 | 975 | */ |
1003 | 976 | int status = KSFT_FAIL << 8; |
1004 | | - int child; |
| 977 | + struct pollfd poll_child; |
| 978 | + int ret, child, childfd; |
| 979 | + bool timed_out = false; |
1005 | 980 |
|
1006 | | - if (sigaction(SIGALRM, &action, &saved_action)) { |
| 981 | + childfd = syscall(__NR_pidfd_open, t->pid, 0); |
| 982 | + if (childfd == -1) { |
1007 | 983 | t->exit_code = KSFT_FAIL; |
1008 | 984 | fprintf(TH_LOG_STREAM, |
1009 | | - "# %s: unable to install SIGALRM handler\n", |
| 985 | + "# %s: unable to open pidfd\n", |
1010 | 986 | t->name); |
1011 | 987 | return; |
1012 | 988 | } |
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) { |
1018 | 994 | t->exit_code = KSFT_FAIL; |
1019 | 995 | 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); |
1022 | 998 | return; |
| 999 | + } else if (ret == 0) { |
| 1000 | + timed_out = true; |
| 1001 | + /* signal process group */ |
| 1002 | + kill(-(t->pid), SIGKILL); |
1023 | 1003 | } |
1024 | | - |
1025 | | - alarm(0); |
1026 | | - if (sigaction(SIGALRM, &saved_action, NULL)) { |
| 1004 | + child = waitpid(t->pid, &status, WNOHANG); |
| 1005 | + if (child == -1 && errno != EINTR) { |
1027 | 1006 | t->exit_code = KSFT_FAIL; |
1028 | 1007 | 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); |
1031 | 1010 | return; |
1032 | 1011 | } |
1033 | | - __active_test = NULL; |
1034 | 1012 |
|
1035 | | - if (t->timed_out) { |
| 1013 | + if (timed_out) { |
1036 | 1014 | t->exit_code = KSFT_FAIL; |
1037 | 1015 | fprintf(TH_LOG_STREAM, |
1038 | 1016 | "# %s: Test terminated by timeout\n", t->name); |
|
0 commit comments