selftests/harness: Move test child waiting logic
authorKees Cook <keescook@chromium.org>
Fri, 13 Mar 2020 23:12:51 +0000 (16:12 -0700)
committerShuah Khan <skhan@linuxfoundation.org>
Thu, 26 Mar 2020 21:27:18 +0000 (15:27 -0600)
In order to better handle timeout failures, rearrange the child waiting
logic into a separate function. This is mostly a copy/paste with an
indentation change. To handle pid tracking, a new field is added for
the child pid. Also move the alarm() pairing into the function.

Signed-off-by: Kees Cook <keescook@chromium.org>
Signed-off-by: Shuah Khan <skhan@linuxfoundation.org>
tools/testing/selftests/kselftest_harness.h

index 5336b26506ab28bbc6b5e2c9d3587aaa193d1435..c7b67e3792196e8ae7e14468cd6411b39f70dffa 100644 (file)
 struct __test_metadata {
        const char *name;
        void (*fn)(struct __test_metadata *);
+       pid_t pid;      /* pid of test when being run */
        int termsig;
        int passed;
        int trigger; /* extra handler after the evaluation */
@@ -695,64 +696,68 @@ static inline int __bail(int for_realz, bool no_print, __u8 step)
        return 0;
 }
 
-void __run_test(struct __test_metadata *t)
+void __wait_for_test(struct __test_metadata *t)
 {
-       pid_t child_pid;
        int status;
 
+       alarm(t->timeout);
+       waitpid(t->pid, &status, 0);
+       alarm(0);
+
+       if (WIFEXITED(status)) {
+               t->passed = t->termsig == -1 ? !WEXITSTATUS(status) : 0;
+               if (t->termsig != -1) {
+                       fprintf(TH_LOG_STREAM,
+                               "%s: Test exited normally "
+                               "instead of by signal (code: %d)\n",
+                               t->name,
+                               WEXITSTATUS(status));
+               } else if (!t->passed) {
+                       fprintf(TH_LOG_STREAM,
+                               "%s: Test failed at step #%d\n",
+                               t->name,
+                               WEXITSTATUS(status));
+               }
+       } else if (WIFSIGNALED(status)) {
+               t->passed = 0;
+               if (WTERMSIG(status) == SIGABRT) {
+                       fprintf(TH_LOG_STREAM,
+                               "%s: Test terminated by assertion\n",
+                               t->name);
+               } else if (WTERMSIG(status) == t->termsig) {
+                       t->passed = 1;
+               } else {
+                       fprintf(TH_LOG_STREAM,
+                               "%s: Test terminated unexpectedly "
+                               "by signal %d\n",
+                               t->name,
+                               WTERMSIG(status));
+               }
+       } else {
+               fprintf(TH_LOG_STREAM,
+                       "%s: Test ended in some other way [%u]\n",
+                       t->name,
+                       status);
+       }
+}
+
+void __run_test(struct __test_metadata *t)
+{
        t->passed = 1;
        t->trigger = 0;
        printf("[ RUN      ] %s\n", t->name);
-       alarm(t->timeout);
-       child_pid = fork();
-       if (child_pid < 0) {
+       t->pid = fork();
+       if (t->pid < 0) {
                printf("ERROR SPAWNING TEST CHILD\n");
                t->passed = 0;
-       } else if (child_pid == 0) {
+       } else if (t->pid == 0) {
                t->fn(t);
                /* return the step that failed or 0 */
                _exit(t->passed ? 0 : t->step);
        } else {
-               /* TODO(wad) add timeout support. */
-               waitpid(child_pid, &status, 0);
-               if (WIFEXITED(status)) {
-                       t->passed = t->termsig == -1 ? !WEXITSTATUS(status) : 0;
-                       if (t->termsig != -1) {
-                               fprintf(TH_LOG_STREAM,
-                                       "%s: Test exited normally "
-                                       "instead of by signal (code: %d)\n",
-                                       t->name,
-                                       WEXITSTATUS(status));
-                       } else if (!t->passed) {
-                               fprintf(TH_LOG_STREAM,
-                                       "%s: Test failed at step #%d\n",
-                                       t->name,
-                                       WEXITSTATUS(status));
-                       }
-               } else if (WIFSIGNALED(status)) {
-                       t->passed = 0;
-                       if (WTERMSIG(status) == SIGABRT) {
-                               fprintf(TH_LOG_STREAM,
-                                       "%s: Test terminated by assertion\n",
-                                       t->name);
-                       } else if (WTERMSIG(status) == t->termsig) {
-                               t->passed = 1;
-                       } else {
-                               fprintf(TH_LOG_STREAM,
-                                       "%s: Test terminated unexpectedly "
-                                       "by signal %d\n",
-                                       t->name,
-                                       WTERMSIG(status));
-                       }
-               } else {
-                       fprintf(TH_LOG_STREAM,
-                               "%s: Test ended in some other way [%u]\n",
-                               t->name,
-                               status);
-               }
+               __wait_for_test(t);
        }
        printf("[     %4s ] %s\n", (t->passed ? "OK" : "FAIL"), t->name);
-       alarm(0);
 }
 
 static int test_harness_run(int __attribute__((unused)) argc,