|
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