Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
[firefly-linux-kernel-4.4.55.git] / tools / testing / selftests / powerpc / harness.c
1 /*
2  * Copyright 2013, Michael Ellerman, IBM Corp.
3  * Licensed under GPLv2.
4  */
5
6 #include <errno.h>
7 #include <signal.h>
8 #include <stdbool.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <sys/types.h>
12 #include <sys/wait.h>
13 #include <unistd.h>
14
15 #include "subunit.h"
16 #include "utils.h"
17
18 #define TIMEOUT         120
19 #define KILL_TIMEOUT    5
20
21
22 int run_test(int (test_function)(void), char *name)
23 {
24         bool terminated;
25         int rc, status;
26         pid_t pid;
27
28         /* Make sure output is flushed before forking */
29         fflush(stdout);
30
31         pid = fork();
32         if (pid == 0) {
33                 setpgid(0, 0);
34                 exit(test_function());
35         } else if (pid == -1) {
36                 perror("fork");
37                 return 1;
38         }
39
40         setpgid(pid, pid);
41
42         /* Wake us up in timeout seconds */
43         alarm(TIMEOUT);
44         terminated = false;
45
46 wait:
47         rc = waitpid(pid, &status, 0);
48         if (rc == -1) {
49                 if (errno != EINTR) {
50                         printf("unknown error from waitpid\n");
51                         return 1;
52                 }
53
54                 if (terminated) {
55                         printf("!! force killing %s\n", name);
56                         kill(-pid, SIGKILL);
57                         return 1;
58                 } else {
59                         printf("!! killing %s\n", name);
60                         kill(-pid, SIGTERM);
61                         terminated = true;
62                         alarm(KILL_TIMEOUT);
63                         goto wait;
64                 }
65         }
66
67         /* Kill anything else in the process group that is still running */
68         kill(-pid, SIGTERM);
69
70         if (WIFEXITED(status))
71                 status = WEXITSTATUS(status);
72         else {
73                 if (WIFSIGNALED(status))
74                         printf("!! child died by signal %d\n", WTERMSIG(status));
75                 else
76                         printf("!! child died by unknown cause\n");
77
78                 status = 1; /* Signal or other */
79         }
80
81         return status;
82 }
83
84 static void alarm_handler(int signum)
85 {
86         /* Jut wake us up from waitpid */
87 }
88
89 static struct sigaction alarm_action = {
90         .sa_handler = alarm_handler,
91 };
92
93 int test_harness(int (test_function)(void), char *name)
94 {
95         int rc;
96
97         test_start(name);
98         test_set_git_version(GIT_VERSION);
99
100         if (sigaction(SIGALRM, &alarm_action, NULL)) {
101                 perror("sigaction");
102                 test_error(name);
103                 return 1;
104         }
105
106         rc = run_test(test_function, name);
107
108         if (rc == MAGIC_SKIP_RETURN_VALUE)
109                 test_skip(name);
110         else
111                 test_finish(name, rc);
112
113         return rc;
114 }